Learning Check
When you complete this session, you will be able to:
- understand the assumptions in SLR;
- understand how to critically assessing a regression model;
- perform regression diagnostics checking for Simple Linear
Regression;
- understand outliers and leverage;
- perform some simple transformations.
Before you start, load the stored datasets provided for exercises
below by running the following chunk (assuming the file
“InsulatingData.Rdata” is saved in the same directory as the .Rmd
worksheet).
Question 1 The timing of production runs (Sheather, 2009)
The original data are in the form of the time taken (in minutes) for
a production run, \(Y\), and the number
of items produced, \(X\), for 20
randomly selected orders as supervised by three managers. At this stage
we shall only consider the data for one of the managers.
(a). Open the Excel file production.txt. Construct a
scatterplot of production run, \(Y\),
and the number of items produced, \(X\). Fit the least squares line to the data
using R. Explain the fitted model, by interpreting the slope and
intercept.
production=read.table("production.txt", header=T)
production
prod.lm=lm(RunTime ~ RunSize, data=production) ## the LS line
prod.lm1=lm(RunTime ~ 10*RunSize, data=production)
Error in terms.formula(formula, data = data) :
invalid model formula in ExtractVars
The equation of the least squares line of best fit is
\[y = 149.7 + 0.26x.\]
The intercept is 149.7, which is where the line of best fit crosses
the run time axis. The intercept in the model has the following
interpretation: for any production run, the average set up time is 149.7
minutes.
The slope of the line is 0.26. Thus, we say that each additional unit
to be produced is predicted to add 0.26 minutes to the run time.
The value of \(R^2= 0.7302\) which
implies that 73.02% of the information (variation) in Run Time is
explained by the least squares regression line, suggesting that the
model is a good model.
(b). Construct residual diagnostic plots, and assess whether you
think that the assumptions for linear regression have been satisfied.
You can use the function rstudent (or
rstandard) to first standardize the residuals.
First, we manually check the normality through histograms and
QQ-plots of residuals and standardised residuals.
names(prod.lm) ## checking the output of the fitted model, residuals
[1] "coefficients" "residuals" "effects" "rank" "fitted.values" "assign" "qr"
[8] "df.residual" "xlevels" "call" "terms" "model"
res=prod.lm$residuals
std.res=rstandard(prod.lm) ## standardised residuals
par(mfrow=c(2,2)) ## plotting 4 plots to check normality
hist(res)
hist(std.res)
qqnorm(std.res)
qqline(std.res)

From the above histograms and QQ-plots, the normality is
satisfied.
par(mfrow=c(2,2))
plot(res, xlab="Time", ylab="Residuals") ## Residuals vs Time
plot(std.res,xlab="Time", ylab="Standardised Residuals")
plot(production$RunSize,res, xlab="Run Size", ylab="Residuals") # Residuals vs x
plot(production$RunSize,std.res, xlab="Run Size", ylab="Standardised Residuals")

- The next residual analysis is to check about randomness (independence) and constant variance. We plot both
residuals and standardised residuals against time (top left and top right). From these plots we can confirm the
the residual are random scattered with no pattern whatsoever.
- The bottom left plot shows the residuals against Run Size to check randomness (no pattern) and constant
variance. The bottom right plot provides the standardised residuals against fitted values to check randomness (no
pattern) and constant variance. Both plots confirm randomness and constant variance.
(c). Using the fitted model.
par(mfrow=c(2,2)) # to view 2x2 plots
plot(prod.lm)


The figure above provides diagnostic plots produced by R when the
command plot(prod.lm) is used, where prod.lm
is the result of the “lm” command.
+ The top left plot shows the residuals against fitted values to check randomness (no pattern) and linearity.
+ The bottom left provides the standardised residuals against fitted values to check randomness (no pattern) and constant variance. The smoothing curve using standardised residuals is almost flat (i.e constant) to confirm randomness and constant variance.
+ The top right plot is a normal Q–Q plot. Most of the observations lie around the straight line, confirming Normality.
+ The bottom right plot of standardized residuals against leverage enables one
to readily identify any ‘bad’ leverage points.
- Recall that the rule for simple linear regression for classifying a point as a leverage
point is if leverage $h_{ii} > 4/ n.$ As $n=20$, the rule is $h_{ii} > 0.2.$ As leverage $h_{ii}$ in the above
bottom right is less than 0.2, then there is no leverage points.
- Recall that we classify points as outliers if their standardized residuals have absolute value greater than
2. All the residuals are within (-2,2), therefore no outliers being detected.
Question 2 The invoices data (Sheather, 2009)
The manager of the purchasing department of a large company would
like to develop a regression model to predict the average amount of time
it takes to process a given number of invoices. Over a 30-day period,
data are collected on the number of invoices processed and the total
time taken (in hours). The data are available in the file
invoices.txt.
Complete the following tasks.
(a). Fit the least squares line to the data using R. Explain the
fitted model, by interpreting the slope and intercept.
invoices=read.table("invoices.txt", header=T)
View(invoices)
inv.lm=lm(Time ~ Invoices, data=invoices)
plot(Time ~ Invoices, data=invoices)
abline(inv.lm)

Call:
lm(formula = Time ~ Invoices, data = invoices)
Residuals:
Min 1Q Median 3Q Max
-0.59516 -0.27851 0.03485 0.19346 0.53083
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.6417099 0.1222707 5.248 1.41e-05 ***
Invoices 0.0112916 0.0008184 13.797 5.17e-14 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.3298 on 28 degrees of freedom
Multiple R-squared: 0.8718, Adjusted R-squared: 0.8672
F-statistic: 190.4 on 1 and 28 DF, p-value: 5.175e-14
The equation of the least squares line of best fit is
\[ Time= 0.642 + 0.011 Invoices
.\]
The intercept is 0.642, which is not interpretable for no
invoices.
The slope of the line is 0.011. Thus, we say for that for each
additional invoice, the average amount of time it takes to process
increases by 0.011 hour.
(b). Construct residual diagnostic plots, and assess whether you
think that the assumptions for linear regression have been satisfied.
You can use the function rstudent (or
rstandard) to first standardize the residuals.
First, we check the normality through histograms and QQ-plots of
residuals and standardised residuals.
names(inv.lm) ## checking the output of the fitted model, residuals
[1] "coefficients" "residuals" "effects" "rank" "fitted.values"
[6] "assign" "qr" "df.residual" "xlevels" "call"
[11] "terms" "model"
res=inv.lm$residuals
std.res=rstandard(inv.lm) ## standardised residuals
par(mfrow=c(2,2)) ## plotting 4 plots to checkk normality
hist(res)
hist(std.res)
qqnorm(std.res)
qqline(std.res)

The histograms show bimodalities. From the QQ-plots, the normality
seems to be satisfied, except 1 point at the top and 1 point at the
bottom respectively.
par(mfrow=c(2,2))
plot(res, xlab="Time", ylab="Residuals")
plot(std.res,xlab="Time", ylab="Standardised Residuals")
plot(res, invoices$Invoices, xlab="Invoices", ylab="Residuals")
plot(std.res, invoices$Invoices, xlab="Invoices", ylab="Standardised Residuals")

The next residual analysis is to check about randomness
(independence) and constant variance. We plot both residuals and
standardised residuals against time (top left and top right). From these
plots we can see a bit of increasing pattern, small residuals within
0-15 and then larger residuals within 15-30.
The bottom left plot shows the residuals against Invoices to check
randomness (no pattern) and constant variance. The bottom right plot
provides the standardised residuals against fitted values to check
randomness (no pattern) and constant variance. Both plots show a bit of
pattern between negative and positive Invoices.
(c). Perform diagnostic checking for the fitted model in (a) using
“plot(file.lm).” Interpret the outputs.
par(mfrow=c(2,2))
plot(inv.lm)

The top left plot shows the residuals against fitted values to
check randomness (no pattern) and linearity.
The bottom left provides the standardised residuals against
fitted values to check randomness (no pattern) and constant variance.
The smoothing curve using standardised residuals is a curve which means
that independence and constant variance may not be satisfied.
The top right plot is a normal Q–Q plot. Most of the observations
lie around the straight line except the two points, confirming
Normality.
The bottom right plot of standardized residuals against leverage
enables one to readily identify any ‘bad’ leverage points.
- Recall that the rule for simple linear regression for classifying a point as a leverage
point is if leverage $h_{ii} > 4/ n.$ As $n=30$, the rule is $h_{ii} > 0.13.$ As leverage $h_{ii}$ in the above
bottom right plot has one point with $h_{ii} > 0.13$ , then there is one leverage point.
- Recall that we classify points as outliers if their standardized residuals have
absolute value greater than 2. All the residuals are within (-2,2), therefore no outliers being detected. The
above leverage point is a `good` leverage point.
(d). Use the function influence.measures to explore
measures of leverage and Cook’s distance.
# check help function first
Inv.infl<-influence.measures(inv.lm)
Inv.infl
Influence measures of
lm(formula = Time ~ Invoices, data = invoices) :
Points increase in influence to the extent that they lie on their
own, a long way from the mean of \(x\)
and the bulk of the data. The column “hat” in the above is the commonest
measure of this leverage and is defined by:
\[h_i = \frac{1}{n} +
\frac{(x_i-\bar{x})^2}{\sum(x_j -\bar{x})^2} .\]
Cook’s distance (the column “cook.d” in the above) is one measure of
influence: for each point, it combines the size of its residual along
with a measure of the leverage. An approximate cutoff is \(4/(n-2)\), but in practice it is important
to look for gaps in values of Cook’s distance instead of just whether or
not the values exceed the cutoff.
There are 2 functions which can also be used to calculate these
measures directly: hatvalues and
cooks.distance.
Leverage.inv<-hatvalues(inv.lm)
Cooks.Dist.inv<-cooks.distance(inv.lm)
Inv <- invoices$Invoices
# plotting the influence measures against their x value - Invoices
n=30
plot(Leverage.inv~Inv)
abline(h=4/n, col=3)
plot(Cooks.Dist.inv~Inv)
abline(h=4/(n-2), col=2)
Recall that we classify points as outliers if their standardized
residuals have absolute value greater than 2. All the residuals are
within (-2,2), therefore no outliers being detected. The above leverage
point is a good leverage point.
Cooks Distance identifies one potential outlier, observation
number 30. However, it is important to look for gaps in values of Cook’s
distance instead of just whether or not the values exceed the
cutoff.
# plotting the influence measures against their x value - Invoices
n=30
plot(Leverage.inv~Inv)
abline(h=4/n, col=3)

plot(Cooks.Dist.inv~Inv)
abline(h=4/(n-2), col=2)

28 26 1 11 24 25 16 15
0.03348526 0.03395333 0.03554890 0.03580511 0.03783426 0.04002682 0.04268500 0.04470347
12 29 9 7 3 17 22 21
0.04695762 0.04875109 0.04933167 0.05065542 0.05402803 0.05548070 0.05552997 0.05775210
2 13 5 27 6 20 8 10
0.06354063 0.06354063 0.06435114 0.06435114 0.06529058 0.07786621 0.08542440 0.09496328
30 18 14 4 23 19
0.09620163 0.09863069 0.10127820 0.10389038 0.10917143 0.18897091
Question 3 (From Weisberg, S. (2005). Applied Linear
Regression, 3rd edition. New York: Wiley)
In this question, you will be learning the R code in more detail to
provide better visualisation which may be needed for your project.
Furthermore, the ANOVA is explained in more detail following the lecture
(part c).
The R data file Wind.RData contains a data
frame (wm1) containing wind speed data (in m/s) at two
sites: a reference site (Rspd) and a candidate site
(CSpd). Data were collected every 6 hours for the year 2002
except in the month of May. The objective is to be able to determine
whether wind speed at the reference site, which has permanent wind speed
monitoring equipment, can be used to predict the wind speed at this
candidate site in the future in order to determine whether to place a
small wind farm there.
10 16 20 8 9 14
0.0002035386 0.0005353096 0.0010595498 0.0011024438 0.0032903108 0.0033298164
17 28 29 4 1 18
0.0036431399 0.0045459002 0.0059479355 0.0061181410 0.0088295724 0.0090501347
7 5 24 25 11 6
0.0092145747 0.0150936105 0.0174505677 0.0201627039 0.0260821401 0.0302309933
21 12 22 26 19 27
0.0308161815 0.0341277200 0.0387338505 0.0423707984 0.0502287555 0.0510541088
3 2 15 13 23 30
0.0599026174 0.0770062759 0.0797769665 0.0898041145 0.1207897984 0.1525784387
- Draw a scatterplot of the response
CSpd against the
predictor RSpd and label it appropriately.
par(pty = "s") # A graphical parameter that sets the PlotTYpe to "square"
# The syntax of the plot statement says "plot CSpd against RSpd but extract them
# from the data frame wm1. The xlim and ylim arguments are the same - the range
# of all the data.
plot(CSpd ~ RSpd, data = wm1,
xlab = "Wind speed at reference site (m/s)",
ylab = "Wind speed at candidate site (m/s)",
main = "Wind speeds at reference and candidate sites",
xlim = range(c(wm1$CSpd, wm1$RSpd)), ylim = c(range(c(wm1$CSpd, wm1$RSpd))))

[1] 1116
Fit a simple linear model to these data, and present the appropriate
regression summaries. Plot the fitted line onto the plot in (a).
# Load the workshop data here
load("Wind.RData")
nrow('Wind.RData')
NULL
To plot the fitted line onto an existing plot in R or RStudio,
you only need to invoke the abline command (from the
console) that we’ve used already and that’s shown below. Here, however,
because I want to produce a separate plot from the one above, I have to
re-plot the data using the above commands and then invoke
abline.
# Notice the similarity with the plot statement above
Wind.lm <- lm(CSpd ~ RSpd, data = wm1)
# Here are the contents of the object Wind.lm:
names(Wind.lm)
[1] "coefficients" "residuals" "effects" "rank" "fitted.values"
[6] "assign" "qr" "df.residual" "xlevels" "call"
[11] "terms" "model"
# and here's some basic output:
Wind.lm
Call:
lm(formula = CSpd ~ RSpd, data = wm1)
Coefficients:
(Intercept) RSpd
3.1412 0.7557
# A bit more comes from the summary() function:
summary(Wind.lm)
Call:
lm(formula = CSpd ~ RSpd, data = wm1)
Residuals:
Min 1Q Median 3Q Max
-7.7877 -1.5864 -0.1994 1.4403 9.1738
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.14123 0.16958 18.52 <2e-16 ***
RSpd 0.75573 0.01963 38.50 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.466 on 1114 degrees of freedom
Multiple R-squared: 0.5709, Adjusted R-squared: 0.5705
F-statistic: 1482 on 1 and 1114 DF, p-value: < 2.2e-16
- Construct the four diagnostic plots that we discussed in the
lecture. Do you think the simple linear model is a good fit? What
improvements might you suggest?
par(pty = "s")
plot(CSpd ~ RSpd, data = wm1,
xlab = "Wind speed at reference site (m/s)",
ylab = "Wind speed at candidate site (m/s)",
main = "Wind speeds at reference and candidate sites",
xlim = range(c(CSpd, RSpd)), ylim = c(range(c(CSpd, RSpd))))
# abline() takes two arguments: a slope and an intercept. We can
# extract these from the object Wind.lm (which is a list) by
# using the $ operator, e.g., Wind.lm$coefficients (try it!) and
# using that as an argument to abline():
abline(Wind.lm$coef) # or simply abline(Wind.lm)

The interpretation:
- Plot 1 - Residuals vs Fitted: There is no clear pattern, eventhough large fitted values seem to have smaller residuals.
- Plot 2 - Scale - Location: There is no clear pattern, eventhough large fitted values seem to have smaller residuals.
- Plot 3 - QQ plot of standardised residuals: while most of the points are on the straight line, some points on the upper part are off the lines. Normality might not be satisfied.
- Plot 4 - Residuals vs Leverage: As $n=1116$ then the cut-off for Cook's distance is $D_i > 4/(n-2)=0.0036.$ We can see that many of the standardised residuals with the leverage greater than 0.04.
Question 4: House selling price data
A set of data on the selling price \(Y\) (in $10,000) and annual taxes \(X\) (in $1,000) for 24 houses is available
available online, {housesellingprice.txt}.
- Assuming that a simple linear regression model is appropriate,
obtain the least squares fit relating selling price to taxes paid. What
is the estimate of \(\sigma^2\)?
Read data in
par(mfrow=c(2,2)) # Places 4 graphs together on the same plotting region
plot(Wind.lm)

Simple Linear regression fit
house = read.table("housesellingprice.txt",header=T)
summary(house)
sales taxes
Min. :25.90 Min. :3.891
1st Qu.:29.90 1st Qu.:5.057
Median :33.70 Median :5.974
Mean :34.61 Mean :6.405
3rd Qu.:38.15 3rd Qu.:7.873
Max. :45.80 Max. :9.142
\(\widehat\beta_0=13.3202\), \(\widehat\beta_1=3.3244\)
house.lm<-lm(sales~taxes,data=house)
summary(house.lm)
Call:
lm(formula = sales ~ taxes, data = house)
Residuals:
Min 1Q Median 3Q Max
-3.8343 -2.3157 -0.3669 1.9787 6.3168
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 13.3202 2.5717 5.179 3.42e-05 ***
taxes 3.3244 0.3903 8.518 2.05e-08 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.961 on 22 degrees of freedom
Multiple R-squared: 0.7673, Adjusted R-squared: 0.7568
F-statistic: 72.56 on 1 and 22 DF, p-value: 2.051e-08
\(\widehat\sigma^2={Residual
MS}=8.77\)
- Find the mean selling price given that the taxes paid are \(7.50\).
Analysis of Variance Table
Response: sales
Df Sum Sq Mean Sq F value Pr(>F)
taxes 1 636.16 636.16 72.556 2.051e-08 ***
Residuals 22 192.89 8.77
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
the mean selling price \(=38.25296\)
that the taxes paid are \(X_0=7.50\).
- Construct a graph of \(Y\) versus
\(X\). Then add the fitted line, the
95% confidence interval of the mean response, and the 95% prediction
interval of the new actual values on the graph.
predict(house.lm,newdata=data.frame(taxes=7.5),interval="confidence",level=0.95)
fit lwr upr
1 38.25296 36.71776 39.78816
- Perform diagnostic checking for the fitted model in (a) using
“plot(file.lm).” Interpret the outputs.
with(house,plot(sales~taxes,type="p"))
with(house,lines(fitted(house.lm)~taxes))
new = data.frame(taxes=seq(3,10,.1))
CIs = predict(house.lm,new,interval="confidence")
PIs = predict(house.lm,new,interval="predict")
matpoints(new$taxes,CIs,lty=c(1,2,2),col=c("black","red","red"),type="l")
matpoints(new$taxes,PIs,lty=c(1,2,2),col=c("black","blue","blue"),type="l")

The top left plot shows the residuals against fitted values to
check randomness (no pattern) and linearity. The smoothing curve shows a
reasonable linear relationship and no pattern.
The bottom left provides the standardised residuals against
fitted values to check randomness (no pattern) and constant variance.
The smoothing curve using standardised residuals is a curve which means
that independence and constant variance may not be satisfied.
The top right plot is a normal Q–Q plot. Most of the observations
lie around the straight line except the two points, confirming
Normality.
The bottom right plot of standardized residuals against leverage
enables one to readily identify any ‘bad’ leverage points.
par(mfrow=c(2,2))
plot(house.lm)

# check help function first
house.lev<-hatvalues(house.lm)
house.lev
1 2 3 4 5 6 7 8
0.08009597 0.07494802 0.10189804 0.10097003 0.07310359 0.15145530 0.04613071 0.05281317
9 10 11 12 13 14 15 16
0.04744471 0.06286388 0.04197728 0.04511789 0.07355860 0.10057696 0.04314772 0.07471120
17 18 19 20 21 22 23 24
0.16214717 0.04466605 0.06413614 0.14091382 0.04346584 0.10811699 0.09396602 0.17177488
- Recall that the rule for simple linear regression for classifying a point as a leverage
point is if leverage $h_{ii} > 4/ n.$ As $n=24$, the rule is $h_{ii} > 0.167.$ As leverage $h_{ii}$ in the
above output shows that one point (observation no 24) with $h_{ii}=0.17177 > 0.167$ , then there is one
leverage point.
- Recall that we classify points as outliers if their standardized residuals have
absolute value greater than 2. There is one observation (no 15) with the standard residual is greater than
2. However observation number 24, the leverage point, with standard residual less than 2 is a good
leverage point.
Question 5 Bid data (Sheather, 2009)
A building maintenance company is planning to submit a bid on a
contract to clean corporate offices scattered throughout an office
complex. The costs incurred by the maintenance company are proportional
to the number of cleaning crews needed for this task. Recent data are
available for the number of rooms that were cleaned by varying numbers
of crews. For a sample of 53 days, records were kept of the number of
crews used and the number of rooms that were cleaned by those crews. The
data can be found in the file cleaning.txt.
The aim is to develop a regression equation to model the relationship
between the number of rooms cleaned and the number of crews.
Complete the following tasks.
(a). Fit the least squares line to the data using R. Explain the
fitted model, by interpreting the slope and intercept.
std.res.h=rstandard(house.lm)
#std.res.h
sort(std.res.h)
14 1 23 11 8 4 22
-1.36539093 -1.32680727 -1.23490307 -1.09307472 -1.05824009 -0.91550077 -0.79182376
12 7 3 2 19 5 13
-0.77096776 -0.70102563 -0.18618750 -0.17949347 -0.17219414 -0.08436379 -0.03798314
10 17 16 20 24 9 6
0.19524305 0.19658735 0.45732239 0.70746820 0.77548911 1.10892170 1.33622425
18 21 15
1.47498387 1.50462011 2.18088723
bid=read.table("cleaning.txt", header=T)
head(bid)
The equation of the least squares line of best fit is
\[Rooms = 1.78 + 3.70 Crews.\]
The intercept is \(1.78 \approx 2\)
which is where the line of best fit crosses the Rooms axis. The
intercept in the model has the following interpretation: for Crews=0,
the average of number of cleaned room is 2.
The slope of the line is \(3.70 \approx
4\). Thus, we say that for each additional crew, it is predicted
to add 4 rooms are being cleaned.
(b). Construct residual diagnostic plots, and assess whether you
think that the assumptions for linear regression have been satisfied.
You can use the function rstudent (or
rstandard) to first standardize the residuals.
First, we manually check the normality through histograms and
QQ-plots of residuals and standardised residuals.
bid.lm=lm(Rooms ~ Crews, data=bid) ## the LS line
plot(Rooms ~ Crews, data=bid, xlab="Number of Crews", ylab="Number of Rooms")
abline(bid.lm)

Call:
lm(formula = Rooms ~ Crews, data = bid)
Residuals:
Min 1Q Median 3Q Max
-15.9990 -4.9901 0.8046 4.0010 17.0010
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.7847 2.0965 0.851 0.399
Crews 3.7009 0.2118 17.472 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 7.336 on 51 degrees of freedom
Multiple R-squared: 0.8569, Adjusted R-squared: 0.854
F-statistic: 305.3 on 1 and 51 DF, p-value: < 2.2e-16
From the above histograms and QQ-plots, the normality is
satisfied.
res.bid=bid.lm$residuals
std.res.bid=rstandard(bid.lm) ## standardised residuals
par(mfrow=c(2,2)) ## plotting 4 plots to check normality
hist(res.bid)
hist(std.res.bid)
qqnorm(res.bid)
qqline(res.bid)
qqnorm(std.res.bid)
qqline(std.res.bid)

- The next residual analysis is to check about randomness (independence) and constant variance. We plot both
residuals and standardised residuals against time (top left and top right). From these plots we can confirm the
the residual are random scattered with no pattern whatsoever. However, there seems to show an increasing trend for variances.
- The bottom left plot shows the residuals against Number of Crews to check randomness (no pattern) and constant variance. The bottom right plot provides the standardised residuals against fitted values to check randomness (no pattern) and constant variance.
- It is clear that the variability in the standardized residuals tends to increase with the number of crews. Thus, the assumption that the variance of the errors is constant appears to be violated in this case.
(c). Perform diagnostic checking for the fitted model in (a) using
“plot(file.lm).” Interpret the outputs.
par(mfrow=c(2,2))
plot(res.bid, xlab="Time", ylab="Residuals") ## Residuals vs Time
plot(std.res.bid,xlab="Time", ylab="Standardised Residuals")
plot(bid$Crews,res.bid, xlab="Number of Crews", ylab="Residuals") # Residuals vs x
plot(bid$Crews,std.res.bid, xlab="Number of Crews", ylab="Standardised Residuals")

- The top left plot shows the residuals against fitted values to check randomness (no pattern) and linearity. The smoothing curve shows a reasonable linear relationship and no pattern.
- The bottom left provides the squared root of standardised residuals against fitted values to check randomness (no pattern) and constant variance. The smoothing curve using standardised residuals is an increasing trend which means that constant variance may not be satisfied.
- The top right plot is a normal Q–Q plot. Most of the observations lie around the straight line except the two points, confirming Normality.
- The bottom right plot of standardized residuals against leverage enables one to readily identify any ‘bad’ leverage points (ie large leverage and large standardised residuals)
(d). As the data on each axis are in the form of counts and are
measured in the same units, the square root transformation of both the
predictor variable and the response variable should be implemented.
Apply these transformations and repeat (a).
par(mfrow=c(2,2))
plot(bid.lm)

(e). Perform diagnostic checking for the fitted model in (d) using
“plot(file.lm).” Interpret the outputs.
bid.sq.lm=lm(sqrt(Rooms) ~ sqrt(Crews), data=bid) ## the LS line
plot(sqrt(Rooms) ~ sqrt(Crews), data=bid, xlab="Square Root of Number of Crews", ylab="Square Root of Number of Rooms")
abline(bid.sq.lm)

Call:
lm(formula = sqrt(Rooms) ~ sqrt(Crews), data = bid)
Residuals:
Min 1Q Median 3Q Max
-1.09825 -0.43988 0.06826 0.42726 1.20275
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.2001 0.2757 0.726 0.471
sqrt(Crews) 1.9016 0.0936 20.316 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.594 on 51 degrees of freedom
Multiple R-squared: 0.89, Adjusted R-squared: 0.8879
F-statistic: 412.7 on 1 and 51 DF, p-value: < 2.2e-16
- After the transformation, the bottom left-hand plot further demonstrates the
benefit of the square root transformation in terms of stabilizing the error term.
- Thus, taking the square root of both the x and the y variables has stabilized
the variance of the random errors and hence produced a valid model.
(f). Predict the number of rooms that can be cleaned by 4 crews and
by 16 crews and its 95% confidence intervals using the models in (a) and
(d) respectively.
Using (a)
par(mfrow=c(2,2))
plot(bid.sq.lm)

Using (d)
conf.pred0=predict(bid.lm,newdata=data.frame(Crews=c(4,16)),interval="prediction",level=0.95)
conf.pred0
fit lwr upr
1 16.58827 1.58941 31.58713
2 60.99899 45.81025 76.18773
- We can see that the prediction interval based on the transformed data is narrower
than that based on the untransformed data when the number of crews is 4 (7.78,
27.21) vs (1.58, 31.59) and wider when the number of crews is 16 [(43.33, 81.55) is
wider than (45.81, 76.19)].
- This is expected as the original scale the data have variance which increases as
the x -variable increases which means that realistic prediction intervals will
get wider as the x -variable increases.
- In summary, ignoring nonconstant variance in the raw data from this example led to
invalid prediction intervals.
LS0tCnRpdGxlOiAiU1RBVDI0MDEgQW5hbHlzaXMgb2YgRXhwZXJpbWVudHMiCmF1dGhvcjogJyoqUHJhY3RpY2FsIFdlZWsgNjogU29sdXRpb25zKionCiNkYXRlOiAiUHJhY3RpY2FsIDIiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgaGlnaGxpZ2h0OiBoYWRkb2NrCiAgICAjIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogZmxhdGx5CiAgICB0b2M6IHllcwogIGh0bWxfbm90ZWJvb2s6CiAgICBoaWdobGlnaHQ6IGhhZGRvY2sKICAgICMgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBmbGF0bHkKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB0b2M6IHllcwotLS0KCgpgYGB7ciBlY2hvPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQocHJvbXB0PUZBTFNFLCBjb21tZW50PU5BLCB0aWR5PVRSVUUsIGVycm9yPVRSVUUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UpCmBgYAoKCiMjIExlYXJuaW5nIENoZWNrCgpXaGVuIHlvdSBjb21wbGV0ZSB0aGlzIHNlc3Npb24sIHlvdSB3aWxsIGJlIGFibGUgdG86CgoxLiB1bmRlcnN0YW5kIHRoZSBhc3N1bXB0aW9ucyBpbiBTTFI7CjIuIHVuZGVyc3RhbmQgaG93IHRvIGNyaXRpY2FsbHkgYXNzZXNzaW5nIGEgcmVncmVzc2lvbiBtb2RlbDsKMy4gcGVyZm9ybSByZWdyZXNzaW9uIGRpYWdub3N0aWNzIGNoZWNraW5nIGZvciBTaW1wbGUgTGluZWFyIFJlZ3Jlc3Npb247CjQuIHVuZGVyc3RhbmQgb3V0bGllcnMgYW5kIGxldmVyYWdlOwo1LiBwZXJmb3JtIHNvbWUgc2ltcGxlIHRyYW5zZm9ybWF0aW9ucy4KCgpCZWZvcmUgeW91IHN0YXJ0LCBsb2FkIHRoZSBzdG9yZWQgZGF0YXNldHMgcHJvdmlkZWQgZm9yIGV4ZXJjaXNlcyBiZWxvdyBieSBydW5uaW5nIHRoZSBmb2xsb3dpbmcgY2h1bmsgKGFzc3VtaW5nIHRoZSBmaWxlICAiSW5zdWxhdGluZ0RhdGEuUmRhdGEiIGlzIHNhdmVkIGluIHRoZSBzYW1lIGRpcmVjdG9yeSBhcyB0aGUgLlJtZCAgd29ya3NoZWV0KS4KCiMjIFF1ZXN0aW9uIDEgVGhlIHRpbWluZyBvZiBwcm9kdWN0aW9uIHJ1bnMgKFNoZWF0aGVyLCAyMDA5KQoKVGhlIG9yaWdpbmFsIGRhdGEgYXJlIGluIHRoZSBmb3JtIG9mIHRoZSB0aW1lIHRha2VuIChpbiBtaW51dGVzKSBmb3IgYSBwcm9kdWN0aW9uIHJ1biwgJFkkLCBhbmQgdGhlIG51bWJlciBvZiBpdGVtcyBwcm9kdWNlZCwKJFgkLCBmb3IgMjAgcmFuZG9tbHkgc2VsZWN0ZWQgb3JkZXJzIGFzIHN1cGVydmlzZWQgYnkgdGhyZWUgbWFuYWdlcnMuIEF0IHRoaXMgc3RhZ2Ugd2Ugc2hhbGwgb25seSBjb25zaWRlciB0aGUgZGF0YSBmb3Igb25lIG9mIHRoZSBtYW5hZ2Vycy4KCihhKS4gT3BlbiB0aGUgRXhjZWwgZmlsZSAqcHJvZHVjdGlvbi50eHQqLiBDb25zdHJ1Y3QgYSBzY2F0dGVycGxvdCBvZiBwcm9kdWN0aW9uIHJ1biwgJFkkLCBhbmQgdGhlIG51bWJlciBvZiBpdGVtcyBwcm9kdWNlZCwgJFgkLiBGaXQgdGhlIGxlYXN0IHNxdWFyZXMgbGluZSB0byB0aGUgZGF0YSB1c2luZyBSLiBFeHBsYWluIHRoZSBmaXR0ZWQgbW9kZWwsIGJ5IGludGVycHJldGluZyB0aGUgc2xvcGUgYW5kIGludGVyY2VwdC4KCmBgYHtyfQpwcm9kdWN0aW9uPXJlYWQudGFibGUoInByb2R1Y3Rpb24udHh0IiwgaGVhZGVyPVQpCnByb2R1Y3Rpb24KYGBgCgpgYGB7cn0KcHJvZC5sbT1sbShSdW5UaW1lIH4gUnVuU2l6ZSwgZGF0YT1wcm9kdWN0aW9uKSAjIyB0aGUgTFMgbGluZQpwcm9kLmxtMT1sbShSdW5UaW1lIH4gUnVuU2l6ZSwgZGF0YT1wcm9kdWN0aW9uKQpwbG90KFJ1blRpbWUgfiBSdW5TaXplLCBkYXRhPXByb2R1Y3Rpb24sIHhsYWI9IlJ1biBTaXplIiwgeWxhYj0iUnVuIFRpbWUiKQphYmxpbmUocHJvZC5sbSkKc3VtbWFyeShwcm9kLmxtKQpgYGAKClRoZSBlcXVhdGlvbiBvZiB0aGUgbGVhc3Qgc3F1YXJlcyBsaW5lIG9mIGJlc3QgZml0IGlzCgokJHkgPSAxNDkuNyArIDAuMjZ4LiQkCgpUaGUgaW50ZXJjZXB0IGlzIDE0OS43LCB3aGljaCBpcyB3aGVyZSB0aGUgbGluZSBvZiBiZXN0IGZpdCBjcm9zc2VzIHRoZSBydW4gdGltZSBheGlzLiBUaGUKaW50ZXJjZXB0IGluIHRoZSBtb2RlbCBoYXMgdGhlIGZvbGxvd2luZyBpbnRlcnByZXRhdGlvbjogZm9yIGFueSBwcm9kdWN0aW9uIHJ1biwgdGhlCmF2ZXJhZ2Ugc2V0IHVwIHRpbWUgaXMgMTQ5LjcgbWludXRlcy4KClRoZSBzbG9wZSBvZiB0aGUgbGluZSBpcyAwLjI2LiBUaHVzLCB3ZSBzYXkgdGhhdCBlYWNoCmFkZGl0aW9uYWwgdW5pdCB0byBiZSBwcm9kdWNlZCBpcyBwcmVkaWN0ZWQgdG8gYWRkIDAuMjYgbWludXRlcyB0byB0aGUgcnVuIHRpbWUuIAoKVGhlIHZhbHVlIG9mICRSXjI9ICAwLjczMDIkIHdoaWNoIGltcGxpZXMgdGhhdCA3My4wMiUgb2YgdGhlIGluZm9ybWF0aW9uICh2YXJpYXRpb24pIGluIFJ1biBUaW1lIGlzIGV4cGxhaW5lZCBieSB0aGUgbGVhc3Qgc3F1YXJlcyByZWdyZXNzaW9uIGxpbmUsIHN1Z2dlc3RpbmcgdGhhdCB0aGUgbW9kZWwgaXMgYSBnb29kIG1vZGVsLgoKKGIpLiAgQ29uc3RydWN0IHJlc2lkdWFsIGRpYWdub3N0aWMgcGxvdHMsIGFuZCBhc3Nlc3Mgd2hldGhlciB5b3UgdGhpbmsgdGhhdCB0aGUgYXNzdW1wdGlvbnMgZm9yIGxpbmVhciByZWdyZXNzaW9uIGhhdmUgYmVlbiBzYXRpc2ZpZWQuIFlvdSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBgcnN0dWRlbnRgIChvciBgcnN0YW5kYXJkYCkgdG8gZmlyc3Qgc3RhbmRhcmRpemUgdGhlIHJlc2lkdWFscy4KCgpGaXJzdCwgd2UgbWFudWFsbHkgY2hlY2sgdGhlICpub3JtYWxpdHkgdGhyb3VnaCBoaXN0b2dyYW1zIGFuZCBRUS1wbG90cyBvZiByZXNpZHVhbHMgYW5kIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMuKgoKYGBge3J9Cm5hbWVzKHByb2QubG0pICAjIyBjaGVja2luZyB0aGUgb3V0cHV0IG9mIHRoZSBmaXR0ZWQgbW9kZWwsIHJlc2lkdWFscwpyZXM9cHJvZC5sbSRyZXNpZHVhbHMKc3RkLnJlcz1yc3RhbmRhcmQocHJvZC5sbSkgICMjIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMKcGFyKG1mcm93PWMoMiwyKSkgICMjIHBsb3R0aW5nIDQgcGxvdHMgdG8gY2hlY2sgbm9ybWFsaXR5Cmhpc3QocmVzKQpoaXN0KHN0ZC5yZXMpCnFxbm9ybShyZXMpCnFxbGluZShyZXMpCnFxbm9ybShzdGQucmVzKQpxcWxpbmUoc3RkLnJlcykKcGFyKG1mcm93PWMoMSwxKSkKYGBgCgpGcm9tIHRoZSBhYm92ZSBoaXN0b2dyYW1zIGFuZCBRUS1wbG90cywgdGhlIG5vcm1hbGl0eSBpcyBzYXRpc2ZpZWQuCgpgYGB7cn0KcGFyKG1mcm93PWMoMiwyKSkKcGxvdChyZXMsIHhsYWI9IlRpbWUiLCB5bGFiPSJSZXNpZHVhbHMiKSAjIyBSZXNpZHVhbHMgdnMgVGltZQpwbG90KHN0ZC5yZXMseGxhYj0iVGltZSIsIHlsYWI9IlN0YW5kYXJkaXNlZCBSZXNpZHVhbHMiKQpwbG90KHByb2R1Y3Rpb24kUnVuU2l6ZSxyZXMsIHhsYWI9IlJ1biBTaXplIiwgeWxhYj0iUmVzaWR1YWxzIikgIyBSZXNpZHVhbHMgdnMgeApwbG90KHByb2R1Y3Rpb24kUnVuU2l6ZSxzdGQucmVzLCAgeGxhYj0iUnVuIFNpemUiLCB5bGFiPSJTdGFuZGFyZGlzZWQgUmVzaWR1YWxzIikKYGBgCgogICAgIC0gVGhlIG5leHQgcmVzaWR1YWwgYW5hbHlzaXMgaXMgdG8gY2hlY2sgYWJvdXQgcmFuZG9tbmVzcyAoaW5kZXBlbmRlbmNlKSBhbmQgY29uc3RhbnQgdmFyaWFuY2UuIFdlIHBsb3QgYm90aAogICAgIHJlc2lkdWFscyBhbmQgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBhZ2FpbnN0IHRpbWUgKHRvcCBsZWZ0IGFuZCB0b3AgcmlnaHQpLiBGcm9tIHRoZXNlIHBsb3RzIHdlIGNhbiBjb25maXJtIHRoZQogICAgIHRoZSByZXNpZHVhbCBhcmUgcmFuZG9tIHNjYXR0ZXJlZCB3aXRoIG5vIHBhdHRlcm4gd2hhdHNvZXZlci4KCiAgICAgLSBUaGUgYm90dG9tIGxlZnQgcGxvdCBzaG93cyB0aGUgcmVzaWR1YWxzIGFnYWluc3QgUnVuIFNpemUgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8gcGF0dGVybikgYW5kIGNvbnN0YW50CiAgICAgdmFyaWFuY2UuIFRoZSBib3R0b20gcmlnaHQgcGxvdCBwcm92aWRlcyB0aGUgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBhZ2FpbnN0IGZpdHRlZCB2YWx1ZXMgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8KICAgICBwYXR0ZXJuKSBhbmQgY29uc3RhbnQgdmFyaWFuY2UuIEJvdGggcGxvdHMgY29uZmlybSByYW5kb21uZXNzIGFuZCBjb25zdGFudCB2YXJpYW5jZS4KCihjKS4gVXNpbmcgdGhlIGZpdHRlZCBtb2RlbC4KCmBgYHtyfQpwYXIobWZyb3c9YygyLDIpKSAjIHRvIHZpZXcgMngyIHBsb3RzCnBsb3QocHJvZC5sbSkKcGxvdChwcm9kLmxtMSkKYGBgCgpUaGUgZmlndXJlIGFib3ZlIHByb3ZpZGVzIGRpYWdub3N0aWMgcGxvdHMgcHJvZHVjZWQgYnkgUiB3aGVuIHRoZSBjb21tYW5kIGBwbG90KHByb2QubG0pYCBpcyB1c2VkLCB3aGVyZSBgcHJvZC5sbWAgaXMgdGhlIHJlc3VsdCBvZiB0aGUg4oCcbG3igJ0gY29tbWFuZC4gCgogICAgKyBUaGUgdG9wIGxlZnQgcGxvdCBzaG93cyB0aGUgcmVzaWR1YWxzIGFnYWluc3QgZml0dGVkIHZhbHVlcyB0byBjaGVjayByYW5kb21uZXNzIChubyBwYXR0ZXJuKSBhbmQgbGluZWFyaXR5LiAKCiAgICArIFRoZSBib3R0b20gbGVmdCBwcm92aWRlcyB0aGUgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBhZ2FpbnN0IGZpdHRlZCB2YWx1ZXMgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8gcGF0dGVybikgYW5kIGNvbnN0YW50IHZhcmlhbmNlLiBUaGUgc21vb3RoaW5nIGN1cnZlIHVzaW5nIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMgaXMgYWxtb3N0IGZsYXQgKGkuZSBjb25zdGFudCkgdG8gY29uZmlybSByYW5kb21uZXNzIGFuZCBjb25zdGFudCB2YXJpYW5jZS4KCiAgICArIFRoZSB0b3AgcmlnaHQgcGxvdCBpcyBhIG5vcm1hbCBR4oCTUSBwbG90LiBNb3N0IG9mIHRoZSBvYnNlcnZhdGlvbnMgbGllIGFyb3VuZCB0aGUgc3RyYWlnaHQgbGluZSwgY29uZmlybWluZyBOb3JtYWxpdHkuCgogICAgKyBUaGUgYm90dG9tIHJpZ2h0IHBsb3Qgb2Ygc3RhbmRhcmRpemVkIHJlc2lkdWFscyBhZ2FpbnN0IGxldmVyYWdlIGVuYWJsZXMgb25lCiAgICB0byByZWFkaWx5IGlkZW50aWZ5IGFueSDigJhiYWTigJkgbGV2ZXJhZ2UgcG9pbnRzLiAKCiAgICAgICAtIFJlY2FsbCB0aGF0IHRoZSBydWxlIGZvciBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gZm9yIGNsYXNzaWZ5aW5nIGEgcG9pbnQgYXMgYSBsZXZlcmFnZQogICAgICAgcG9pbnQgaXMgaWYgbGV2ZXJhZ2UgJGhfe2lpfSA+IDQvIG4uJCBBcyAkbj0yMCQsIHRoZSBydWxlIGlzICRoX3tpaX0gPiAwLjIuJCBBcyBsZXZlcmFnZSAkaF97aWl9JCBpbiB0aGUgYWJvdmUKICAgICAgIGJvdHRvbSByaWdodCBpcyBsZXNzIHRoYW4gMC4yLCB0aGVuIHRoZXJlIGlzIG5vIGxldmVyYWdlIHBvaW50cy4KCiAgICAgICAtIFJlY2FsbCB0aGF0IHdlIGNsYXNzaWZ5IHBvaW50cyBhcyBvdXRsaWVycyBpZiB0aGVpciBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzIGhhdmUgYWJzb2x1dGUgdmFsdWUgZ3JlYXRlciB0aGFuCiAgICAgICAyLiBBbGwgdGhlIHJlc2lkdWFscyBhcmUgd2l0aGluICgtMiwyKSwgdGhlcmVmb3JlIG5vIG91dGxpZXJzIGJlaW5nIGRldGVjdGVkLgoKCiMjIFF1ZXN0aW9uIDIgVGhlIGludm9pY2VzIGRhdGEgKFNoZWF0aGVyLCAyMDA5KQoKVGhlIG1hbmFnZXIgb2YgdGhlIHB1cmNoYXNpbmcgZGVwYXJ0bWVudCBvZiBhIGxhcmdlIGNvbXBhbnkgd291bGQgbGlrZSB0bwpkZXZlbG9wIGEgcmVncmVzc2lvbiBtb2RlbCB0byBwcmVkaWN0IHRoZSBhdmVyYWdlIGFtb3VudCBvZiB0aW1lIGl0IHRha2VzIHRvIHByb2Nlc3MgYSBnaXZlbiBudW1iZXIgb2YgaW52b2ljZXMuIE92ZXIgYSAzMC1kYXkgcGVyaW9kLCBkYXRhIGFyZSBjb2xsZWN0ZWQgb24gdGhlIG51bWJlciBvZiBpbnZvaWNlcyBwcm9jZXNzZWQgYW5kIHRoZSB0b3RhbCB0aW1lIHRha2VuIChpbiBob3VycykuIFRoZSBkYXRhIGFyZSBhdmFpbGFibGUgaW4gdGhlIGZpbGUgKmludm9pY2VzLnR4dC4qIAoKQ29tcGxldGUgdGhlIGZvbGxvd2luZyB0YXNrcy4KCihhKS4gRml0IHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgdG8gdGhlIGRhdGEgdXNpbmcgUi4gRXhwbGFpbiB0aGUgZml0dGVkIG1vZGVsLCBieSBpbnRlcnByZXRpbmcgdGhlIHNsb3BlIGFuZCBpbnRlcmNlcHQuCgpgYGB7cn0KaW52b2ljZXM9cmVhZC50YWJsZSgiaW52b2ljZXMudHh0IiwgaGVhZGVyPVQpClZpZXcoaW52b2ljZXMpCmBgYAoKYGBge3J9Cmludi5sbT1sbShUaW1lIH4gSW52b2ljZXMsIGRhdGE9aW52b2ljZXMpCnBsb3QoVGltZSB+IEludm9pY2VzLCBkYXRhPWludm9pY2VzKQphYmxpbmUoaW52LmxtKQpzdW1tYXJ5KGludi5sbSkKYGBgCgpUaGUgZXF1YXRpb24gb2YgdGhlIGxlYXN0IHNxdWFyZXMgbGluZSBvZiBiZXN0IGZpdCBpcwoKJCQgVGltZT0gMC42NDIgKyAwLjAxMSBJbnZvaWNlcyAuJCQKClRoZSBpbnRlcmNlcHQgaXMgMC42NDIsIHdoaWNoIGlzIG5vdCBpbnRlcnByZXRhYmxlIGZvciBubyBpbnZvaWNlcy4KClRoZSBzbG9wZSBvZiB0aGUgbGluZSBpcyAwLjAxMS4gVGh1cywgd2Ugc2F5IGZvciB0aGF0IGZvciBlYWNoCmFkZGl0aW9uYWwgaW52b2ljZSwgdGhlIGF2ZXJhZ2UgYW1vdW50IG9mIHRpbWUgaXQgdGFrZXMgdG8gcHJvY2VzcyBpbmNyZWFzZXMgYnkgMC4wMTEgaG91ci4KCihiKS4gQ29uc3RydWN0IHJlc2lkdWFsIGRpYWdub3N0aWMgcGxvdHMsIGFuZCBhc3Nlc3Mgd2hldGhlciB5b3UgdGhpbmsgdGhhdCB0aGUgYXNzdW1wdGlvbnMgZm9yIGxpbmVhciByZWdyZXNzaW9uIGhhdmUgYmVlbiBzYXRpc2ZpZWQuIFlvdSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBgcnN0dWRlbnRgIChvciBgcnN0YW5kYXJkYCkgdG8gZmlyc3Qgc3RhbmRhcmRpemUgdGhlIHJlc2lkdWFscy4KCkZpcnN0LCB3ZSBjaGVjayB0aGUgbm9ybWFsaXR5IHRocm91Z2ggaGlzdG9ncmFtcyBhbmQgUVEtcGxvdHMgb2YgcmVzaWR1YWxzIGFuZCBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzLgoKYGBge3J9Cm5hbWVzKGludi5sbSkgICMjIGNoZWNraW5nIHRoZSBvdXRwdXQgb2YgdGhlIGZpdHRlZCBtb2RlbCwgcmVzaWR1YWxzCnJlcz1pbnYubG0kcmVzaWR1YWxzCnN0ZC5yZXM9cnN0YW5kYXJkKGludi5sbSkgICMjIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMKcGFyKG1mcm93PWMoMiwyKSkgICMjIHBsb3R0aW5nIDQgcGxvdHMgdG8gY2hlY2trIG5vcm1hbGl0eQpoaXN0KHJlcykKaGlzdChzdGQucmVzKQpxcW5vcm0ocmVzKQpxcWxpbmUocmVzKQpxcW5vcm0oc3RkLnJlcykKcXFsaW5lKHN0ZC5yZXMpCnBhcihtZnJvdz1jKDEsMSkpCmBgYAoKVGhlIGhpc3RvZ3JhbXMgc2hvdyBiaW1vZGFsaXRpZXMuIEZyb20gdGhlIFFRLXBsb3RzLCB0aGUgbm9ybWFsaXR5IHNlZW1zIHRvIGJlIHNhdGlzZmllZCwgZXhjZXB0IDEgcG9pbnQgYXQgdGhlIHRvcCBhbmQgMSBwb2ludCBhdCB0aGUgYm90dG9tIHJlc3BlY3RpdmVseS4KCmBgYHtyfQpwYXIobWZyb3c9YygyLDIpKQpwbG90KHJlcywgeGxhYj0iVGltZSIsIHlsYWI9IlJlc2lkdWFscyIpCnBsb3Qoc3RkLnJlcyx4bGFiPSJUaW1lIiwgeWxhYj0iU3RhbmRhcmRpc2VkIFJlc2lkdWFscyIpCnBsb3QocmVzLCBpbnZvaWNlcyRJbnZvaWNlcywgeGxhYj0iSW52b2ljZXMiLCB5bGFiPSJSZXNpZHVhbHMiKQpwbG90KHN0ZC5yZXMsIGludm9pY2VzJEludm9pY2VzLCAgeGxhYj0iSW52b2ljZXMiLCB5bGFiPSJTdGFuZGFyZGlzZWQgUmVzaWR1YWxzIikKYGBgCgpUaGUgbmV4dCByZXNpZHVhbCBhbmFseXNpcyBpcyB0byBjaGVjayBhYm91dCByYW5kb21uZXNzIChpbmRlcGVuZGVuY2UpIGFuZCBjb25zdGFudCB2YXJpYW5jZS4gV2UgcGxvdCBib3RoIHJlc2lkdWFscyBhbmQgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBhZ2FpbnN0IHRpbWUgKHRvcCBsZWZ0IGFuZCB0b3AgcmlnaHQpLiBGcm9tIHRoZXNlIHBsb3RzIHdlIGNhbiBzZWUgYSBiaXQgb2YgaW5jcmVhc2luZyBwYXR0ZXJuLCBzbWFsbCByZXNpZHVhbHMgd2l0aGluIDAtMTUgYW5kIHRoZW4gbGFyZ2VyIHJlc2lkdWFscyB3aXRoaW4gMTUtMzAuCgpUaGUgYm90dG9tIGxlZnQgcGxvdCBzaG93cyB0aGUgcmVzaWR1YWxzIGFnYWluc3QgSW52b2ljZXMgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8gcGF0dGVybikgYW5kIGNvbnN0YW50IHZhcmlhbmNlLiBUaGUgYm90dG9tIHJpZ2h0IHBsb3QgcHJvdmlkZXMgdGhlIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMgYWdhaW5zdCBmaXR0ZWQgdmFsdWVzIHRvIGNoZWNrIHJhbmRvbW5lc3MgKG5vIHBhdHRlcm4pIGFuZCBjb25zdGFudCB2YXJpYW5jZS4gQm90aCBwbG90cyBzaG93IGEgYml0IG9mIHBhdHRlcm4gYmV0d2VlbiBuZWdhdGl2ZSBhbmQgcG9zaXRpdmUgSW52b2ljZXMuCgooYykuIFBlcmZvcm0gZGlhZ25vc3RpYyBjaGVja2luZyBmb3IgdGhlIGZpdHRlZCBtb2RlbCBpbiAoYSkgdXNpbmcgInBsb3QoZmlsZS5sbSkuIiBJbnRlcnByZXQgdGhlIG91dHB1dHMuCgoKYGBge3J9CnBhcihtZnJvdz1jKDIsMikpCnBsb3QoaW52LmxtKQpgYGAKCgorIFRoZSB0b3AgbGVmdCBwbG90IHNob3dzIHRoZSByZXNpZHVhbHMgYWdhaW5zdCBmaXR0ZWQgdmFsdWVzIHRvIGNoZWNrIHJhbmRvbW5lc3MgKG5vIHBhdHRlcm4pIGFuZCBsaW5lYXJpdHkuIAoKKyBUaGUgYm90dG9tIGxlZnQgcHJvdmlkZXMgdGhlIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMgYWdhaW5zdCBmaXR0ZWQgdmFsdWVzIHRvIGNoZWNrIHJhbmRvbW5lc3MgKG5vIHBhdHRlcm4pIGFuZCBjb25zdGFudCB2YXJpYW5jZS4gVGhlIHNtb290aGluZyBjdXJ2ZSB1c2luZyBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIGlzIGEgY3VydmUgd2hpY2ggbWVhbnMgdGhhdCBpbmRlcGVuZGVuY2UgYW5kIGNvbnN0YW50IHZhcmlhbmNlIG1heSBub3QgYmUgc2F0aXNmaWVkLgoKKyBUaGUgdG9wIHJpZ2h0IHBsb3QgaXMgYSBub3JtYWwgUeKAk1EgcGxvdC4gTW9zdCBvZiB0aGUgb2JzZXJ2YXRpb25zIGxpZSBhcm91bmQgdGhlIHN0cmFpZ2h0IGxpbmUgZXhjZXB0IHRoZSB0d28gcG9pbnRzLCBjb25maXJtaW5nIE5vcm1hbGl0eS4KCisgVGhlIGJvdHRvbSByaWdodCBwbG90IG9mIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgYWdhaW5zdCBsZXZlcmFnZSBlbmFibGVzIG9uZQp0byByZWFkaWx5IGlkZW50aWZ5IGFueSDigJhiYWTigJkgbGV2ZXJhZ2UgcG9pbnRzLiAKCiAgICAgICAtIFJlY2FsbCB0aGF0IHRoZSBydWxlIGZvciBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gZm9yIGNsYXNzaWZ5aW5nIGEgcG9pbnQgYXMgYSBsZXZlcmFnZQogICAgICAgcG9pbnQgaXMgaWYgbGV2ZXJhZ2UgJGhfe2lpfSA+IDQvIG4uJCBBcyAkbj0zMCQsIHRoZSBydWxlIGlzICRoX3tpaX0gPiAwLjEzLiQgQXMgbGV2ZXJhZ2UgJGhfe2lpfSQgaW4gdGhlIGFib3ZlCiAgICAgICBib3R0b20gcmlnaHQgcGxvdCBoYXMgb25lIHBvaW50IHdpdGggJGhfe2lpfSA+IDAuMTMkICwgdGhlbiB0aGVyZSBpcyBvbmUgbGV2ZXJhZ2UgcG9pbnQuCgogICAgICAtIFJlY2FsbCB0aGF0IHdlIGNsYXNzaWZ5IHBvaW50cyBhcyBvdXRsaWVycyBpZiB0aGVpciBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzIGhhdmUKICAgICAgYWJzb2x1dGUgdmFsdWUgZ3JlYXRlciB0aGFuIDIuIEFsbCB0aGUgcmVzaWR1YWxzIGFyZSB3aXRoaW4gKC0yLDIpLCB0aGVyZWZvcmUgbm8gb3V0bGllcnMgYmVpbmcgZGV0ZWN0ZWQuIFRoZQogICAgICBhYm92ZSBsZXZlcmFnZSBwb2ludCBpcyBhIGBnb29kYCBsZXZlcmFnZSBwb2ludC4KCihkKS4gVXNlIHRoZSBmdW5jdGlvbiBgaW5mbHVlbmNlLm1lYXN1cmVzYCB0byBleHBsb3JlIG1lYXN1cmVzIG9mIGxldmVyYWdlIGFuZCBDb29rJ3MgZGlzdGFuY2UuICAgCgpgYGB7cn0KIyBjaGVjayBoZWxwIGZ1bmN0aW9uIGZpcnN0Ckludi5pbmZsPC1pbmZsdWVuY2UubWVhc3VyZXMoaW52LmxtKQpJbnYuaW5mbAojaGVhZChJbnYuaW5mbCRpbmZtYXQpCmBgYAoKUG9pbnRzIGluY3JlYXNlIGluIGluZmx1ZW5jZSB0byB0aGUgZXh0ZW50IHRoYXQgdGhleSBsaWUgb24gdGhlaXIgb3duLCBhIGxvbmcgd2F5IGZyb20gdGhlIG1lYW4gb2YgJHgkIGFuZCB0aGUgYnVsayBvZiB0aGUgZGF0YS4gVGhlIGNvbHVtbiAiaGF0IiBpbiB0aGUgYWJvdmUgaXMgdGhlIGNvbW1vbmVzdCBtZWFzdXJlIG9mIHRoaXMgbGV2ZXJhZ2UgYW5kIGlzIGRlZmluZWQgYnk6CgokJGhfaSA9IFxmcmFjezF9e259ICsgXGZyYWN7KHhfaS1cYmFye3h9KV4yfXtcc3VtKHhfaiAtXGJhcnt4fSleMn0gLiQkCgoKQ29va+KAmXMgZGlzdGFuY2UgKHRoZSBjb2x1bW4gImNvb2suZCIgaW4gdGhlIGFib3ZlKSBpcyBvbmUgbWVhc3VyZSBvZiBpbmZsdWVuY2U6IGZvciBlYWNoIHBvaW50LCBpdCBjb21iaW5lcyB0aGUgc2l6ZSBvZiBpdHMgcmVzaWR1YWwgYWxvbmcgd2l0aCBhIG1lYXN1cmUgb2YgdGhlIGxldmVyYWdlLiBBbiBhcHByb3hpbWF0ZSBjdXRvZmYgaXMgJDQvKG4tMikkLCBidXQgaW4gcHJhY3RpY2UgaXQgaXMgaW1wb3J0YW50IHRvIGxvb2sgZm9yIGdhcHMgaW4gdmFsdWVzIG9mIENvb2vigJlzIGRpc3RhbmNlIGluc3RlYWQgb2YganVzdCB3aGV0aGVyIG9yIG5vdCB0aGUgdmFsdWVzIGV4Y2VlZCB0aGUgY3V0b2ZmLgoKVGhlcmUgYXJlIDIgZnVuY3Rpb25zIHdoaWNoIGNhbiBhbHNvIGJlIHVzZWQgdG8gY2FsY3VsYXRlIHRoZXNlIG1lYXN1cmVzIGRpcmVjdGx5OiBgaGF0dmFsdWVzYCBhbmQgYGNvb2tzLmRpc3RhbmNlYC4KCmBgYHtyfQpMZXZlcmFnZS5pbnY8LWhhdHZhbHVlcyhpbnYubG0pCkNvb2tzLkRpc3QuaW52PC1jb29rcy5kaXN0YW5jZShpbnYubG0pCkludiA8LSBpbnZvaWNlcyRJbnZvaWNlcwpgYGAKCgpgYGB7ciwgZmlnMywgZmlnLndpZHRoID0gNSwgZmlnLmFzcCA9IC41fQojIHBsb3R0aW5nIHRoZSBpbmZsdWVuY2UgbWVhc3VyZXMgYWdhaW5zdCB0aGVpciB4IHZhbHVlIC0gSW52b2ljZXMgCm49MzAKcGxvdChMZXZlcmFnZS5pbnZ+SW52KQphYmxpbmUoaD00L24sIGNvbD0zKQpwbG90KENvb2tzLkRpc3QuaW52fkludikKYWJsaW5lKGg9NC8obi0yKSwgY29sPTIpCmBgYAoKLSBSZWNhbGwgdGhhdCB3ZSBjbGFzc2lmeSBwb2ludHMgYXMgb3V0bGllcnMgaWYgdGhlaXIgc3RhbmRhcmRpemVkIHJlc2lkdWFscyBoYXZlCmFic29sdXRlIHZhbHVlIGdyZWF0ZXIgdGhhbiAyLiBBbGwgdGhlIHJlc2lkdWFscyBhcmUgd2l0aGluICgtMiwyKSwgdGhlcmVmb3JlIG5vIG91dGxpZXJzIGJlaW5nIGRldGVjdGVkLiBUaGUgYWJvdmUgbGV2ZXJhZ2UgcG9pbnQgaXMgYSBgZ29vZGAgbGV2ZXJhZ2UgcG9pbnQuCgotIENvb2tzIERpc3RhbmNlIGlkZW50aWZpZXMgb25lIHBvdGVudGlhbCBvdXRsaWVyLCBvYnNlcnZhdGlvbiBudW1iZXIgMzAuIEhvd2V2ZXIsIGl0IGlzIGltcG9ydGFudCB0byBsb29rIGZvciBnYXBzIGluIHZhbHVlcyBvZiBDb29r4oCZcyBkaXN0YW5jZSBpbnN0ZWFkIG9mIGp1c3Qgd2hldGhlciBvciBub3QgdGhlIHZhbHVlcyBleGNlZWQgdGhlIGN1dG9mZi4KCgoKYGBge3J9CnNvcnQoTGV2ZXJhZ2UuaW52KQpgYGAKCmBgYHtyfQpzb3J0KENvb2tzLkRpc3QuaW52KQpgYGAKCgojIyBRdWVzdGlvbiAzIChGcm9tIFdlaXNiZXJnLCBTLiAoMjAwNSkuICpBcHBsaWVkIExpbmVhciBSZWdyZXNzaW9uKiwgM3JkIGVkaXRpb24uIE5ldyBZb3JrOiBXaWxleSkKCkluIHRoaXMgcXVlc3Rpb24sIHlvdSB3aWxsIGJlIGxlYXJuaW5nIHRoZSBSIGNvZGUgaW4gbW9yZSBkZXRhaWwgdG8gcHJvdmlkZSBiZXR0ZXIgdmlzdWFsaXNhdGlvbiB3aGljaCBtYXkgYmUgbmVlZGVkIGZvciB5b3VyIHByb2plY3QuIEZ1cnRoZXJtb3JlLCB0aGUgQU5PVkEgaXMgZXhwbGFpbmVkIGluIG1vcmUgZGV0YWlsIGZvbGxvd2luZyB0aGUgbGVjdHVyZSAocGFydCBjKS4KClRoZSAqUiogZGF0YSBmaWxlIGBXaW5kLlJEYXRhYCBjb250YWlucyBhIGRhdGEgZnJhbWUgKGB3bTFgKSBjb250YWluaW5nIHdpbmQgc3BlZWQgZGF0YSAoaW4gbS9zKSBhdCB0d28gc2l0ZXM6IGEgcmVmZXJlbmNlIHNpdGUgKGBSc3BkYCkgYW5kIGEgY2FuZGlkYXRlIHNpdGUgKGBDU3BkYCkuIERhdGEgd2VyZSBjb2xsZWN0ZWQgZXZlcnkgNiBob3VycyBmb3IgdGhlIHllYXIgMjAwMiBleGNlcHQgaW4gdGhlIG1vbnRoIG9mIE1heS4gVGhlIG9iamVjdGl2ZSBpcyB0byBiZSBhYmxlIHRvIGRldGVybWluZSB3aGV0aGVyIHdpbmQgc3BlZWQgYXQgdGhlIHJlZmVyZW5jZSBzaXRlLCB3aGljaCBoYXMgcGVybWFuZW50IHdpbmQgc3BlZWQgbW9uaXRvcmluZyBlcXVpcG1lbnQsIGNhbiBiZSB1c2VkIHRvIHByZWRpY3QgdGhlIHdpbmQgc3BlZWQgYXQgdGhpcyBjYW5kaWRhdGUgc2l0ZSBpbiB0aGUgZnV0dXJlIGluIG9yZGVyIHRvIGRldGVybWluZSB3aGV0aGVyIHRvIHBsYWNlIGEgc21hbGwgd2luZCBmYXJtIHRoZXJlLgoKYGBge3J9CiMgTG9hZCB0aGUgd29ya3Nob3AgZGF0YSBoZXJlCmxvYWQoIldpbmQuUkRhdGEiKQpucm93KCdXaW5kLlJEYXRhJykKYGBgCgoKYS4gRHJhdyBhIHNjYXR0ZXJwbG90IG9mIHRoZSByZXNwb25zZSBgQ1NwZGAgYWdhaW5zdCB0aGUgcHJlZGljdG9yIGBSU3BkYCBhbmQgbGFiZWwgaXQgYXBwcm9wcmlhdGVseS4gCgpgYGB7ciBQbG90RGF0YSwgZmlnLmhlaWdodD03fQpwYXIocHR5ID0gInMiKSAjIEEgZ3JhcGhpY2FsIHBhcmFtZXRlciB0aGF0IHNldHMgdGhlIFBsb3RUWXBlIHRvICJzcXVhcmUiCgojIFRoZSBzeW50YXggb2YgdGhlIHBsb3Qgc3RhdGVtZW50IHNheXMgInBsb3QgQ1NwZCBhZ2FpbnN0IFJTcGQgYnV0IGV4dHJhY3QgdGhlbSAKIyBmcm9tIHRoZSBkYXRhIGZyYW1lIHdtMS4gVGhlIHhsaW0gYW5kIHlsaW0gYXJndW1lbnRzIGFyZSB0aGUgc2FtZSAtIHRoZSByYW5nZSAKIyBvZiBhbGwgdGhlIGRhdGEuIApwbG90KENTcGQgfiBSU3BkLCBkYXRhID0gd20xLCAKICAgICB4bGFiID0gIldpbmQgc3BlZWQgYXQgcmVmZXJlbmNlIHNpdGUgKG0vcykiLCAKICAgICB5bGFiID0gIldpbmQgc3BlZWQgYXQgY2FuZGlkYXRlIHNpdGUgKG0vcykiLAogICAgIG1haW4gPSAiV2luZCBzcGVlZHMgYXQgcmVmZXJlbmNlIGFuZCBjYW5kaWRhdGUgc2l0ZXMiLAogICAgIHhsaW0gPSByYW5nZShjKHdtMSRDU3BkLCB3bTEkUlNwZCkpLCB5bGltID0gYyhyYW5nZShjKHdtMSRDU3BkLCB3bTEkUlNwZCkpKSkgCgpucm93KHdtMSkKYGBgCgpGaXQgYSBzaW1wbGUgbGluZWFyIG1vZGVsIHRvIHRoZXNlIGRhdGEsIGFuZCBwcmVzZW50IHRoZSBhcHByb3ByaWF0ZSByZWdyZXNzaW9uIHN1bW1hcmllcy4gUGxvdCB0aGUgZml0dGVkIGxpbmUgb250byB0aGUgcGxvdCBpbiAoYSkuCgpgYGB7cn0KIyBOb3RpY2UgdGhlIHNpbWlsYXJpdHkgd2l0aCB0aGUgcGxvdCBzdGF0ZW1lbnQgYWJvdmUKV2luZC5sbSA8LSBsbShDU3BkIH4gUlNwZCwgZGF0YSA9IHdtMSkKIyBIZXJlIGFyZSB0aGUgY29udGVudHMgb2YgdGhlIG9iamVjdCBXaW5kLmxtOgpuYW1lcyhXaW5kLmxtKQojIGFuZCBoZXJlJ3Mgc29tZSBiYXNpYyBvdXRwdXQ6CldpbmQubG0KCiMgQSBiaXQgbW9yZSBjb21lcyBmcm9tIHRoZSBzdW1tYXJ5KCkgZnVuY3Rpb246CnN1bW1hcnkoV2luZC5sbSkKYGBgCgogICpUbyBwbG90IHRoZSBmaXR0ZWQgbGluZSBvbnRvIGFuIGV4aXN0aW5nIHBsb3QgaW4gUiBvciBSU3R1ZGlvLCB5b3Ugb25seSBuZWVkIHRvIGludm9rZSB0aGUgYGFibGluZWAgY29tbWFuZCAoZnJvbSB0aGUgY29uc29sZSkgdGhhdCB3ZSd2ZSB1c2VkIGFscmVhZHkgYW5kIHRoYXQncyBzaG93biBiZWxvdy4gSGVyZSwgaG93ZXZlciwgYmVjYXVzZSBJIHdhbnQgdG8gcHJvZHVjZSBhIHNlcGFyYXRlIHBsb3QgZnJvbSB0aGUgb25lIGFib3ZlLCBJIGhhdmUgdG8gcmUtcGxvdCB0aGUgZGF0YSB1c2luZyB0aGUgYWJvdmUgY29tbWFuZHMgYW5kIHRoZW4gaW52b2tlIGBhYmxpbmVgLioKICAKYGBge3IgZmlnLmhlaWdodD03fQpwYXIocHR5ID0gInMiKQpwbG90KENTcGQgfiBSU3BkLCBkYXRhID0gd20xLCAKICAgICB4bGFiID0gIldpbmQgc3BlZWQgYXQgcmVmZXJlbmNlIHNpdGUgKG0vcykiLCAKICAgICB5bGFiID0gIldpbmQgc3BlZWQgYXQgY2FuZGlkYXRlIHNpdGUgKG0vcykiLAogICAgIG1haW4gPSAiV2luZCBzcGVlZHMgYXQgcmVmZXJlbmNlIGFuZCBjYW5kaWRhdGUgc2l0ZXMiLAogICAgIHhsaW0gPSByYW5nZShjKENTcGQsIFJTcGQpKSwgeWxpbSA9IGMocmFuZ2UoYyhDU3BkLCBSU3BkKSkpKSAKIyBhYmxpbmUoKSB0YWtlcyB0d28gYXJndW1lbnRzOiBhIHNsb3BlIGFuZCBhbiBpbnRlcmNlcHQuIFdlIGNhbgojIGV4dHJhY3QgdGhlc2UgZnJvbSB0aGUgb2JqZWN0IFdpbmQubG0gKHdoaWNoIGlzIGEgbGlzdCkgYnkgCiMgdXNpbmcgdGhlICQgb3BlcmF0b3IsIGUuZy4sIFdpbmQubG0kY29lZmZpY2llbnRzICh0cnkgaXQhKSBhbmQKIyB1c2luZyB0aGF0IGFzIGFuIGFyZ3VtZW50IHRvIGFibGluZSgpOgphYmxpbmUoV2luZC5sbSRjb2VmKSAjIG9yIHNpbXBseSBhYmxpbmUoV2luZC5sbSkKYGBgICAKCgpiLiBDb25zdHJ1Y3QgdGhlIGZvdXIgZGlhZ25vc3RpYyBwbG90cyB0aGF0IHdlIGRpc2N1c3NlZCBpbiB0aGUgbGVjdHVyZS4gRG8geW91IHRoaW5rIHRoZSBzaW1wbGUgbGluZWFyIG1vZGVsIGlzIGEgZ29vZCBmaXQ/IFdoYXQgaW1wcm92ZW1lbnRzIG1pZ2h0IHlvdSBzdWdnZXN0PwoKYGBge3J9CnBhcihtZnJvdz1jKDIsMikpICAjIFBsYWNlcyA0IGdyYXBocyB0b2dldGhlciBvbiB0aGUgc2FtZSBwbG90dGluZyByZWdpb24KcGxvdChXaW5kLmxtKQpgYGAKClRoZSBpbnRlcnByZXRhdGlvbjoKCiAgICAgICAgIC0gUGxvdCAxIC0gUmVzaWR1YWxzIHZzIEZpdHRlZDogVGhlcmUgaXMgbm8gY2xlYXIgcGF0dGVybiwgZXZlbnRob3VnaCBsYXJnZSBmaXR0ZWQgdmFsdWVzIHNlZW0gdG8gaGF2ZSBzbWFsbGVyIHJlc2lkdWFscy4KCiAgICAgICAgIC0gUGxvdCAyIC0gU2NhbGUgLSBMb2NhdGlvbjogVGhlcmUgaXMgbm8gY2xlYXIgcGF0dGVybiwgZXZlbnRob3VnaCBsYXJnZSBmaXR0ZWQgdmFsdWVzIHNlZW0gdG8gaGF2ZSBzbWFsbGVyIHJlc2lkdWFscy4KCiAgICAgICAgIC0gUGxvdCAzIC0gUVEgcGxvdCBvZiBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzOiB3aGlsZSBtb3N0IG9mIHRoZSBwb2ludHMgYXJlIG9uIHRoZSBzdHJhaWdodCBsaW5lLCBzb21lIHBvaW50cyBvbiB0aGUgdXBwZXIgcGFydCBhcmUgb2ZmIHRoZSBsaW5lcy4gTm9ybWFsaXR5IG1pZ2h0IG5vdCBiZSBzYXRpc2ZpZWQuCgogICAgICAgICAtIFBsb3QgNCAtIFJlc2lkdWFscyB2cyBMZXZlcmFnZTogQXMgJG49MTExNiQgdGhlbiB0aGUgY3V0LW9mZiBmb3IgQ29vaydzIGRpc3RhbmNlIGlzICREX2kgPiA0LyhuLTIpPTAuMDAzNi4kIFdlIGNhbiBzZWUgdGhhdCBtYW55IG9mIHRoZSBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIHdpdGggdGhlIGxldmVyYWdlIGdyZWF0ZXIgdGhhbiAwLjA0LiAKICAgICAgICAgCgojIyBRdWVzdGlvbiA0OiBIb3VzZSBzZWxsaW5nIHByaWNlIGRhdGEKCkEgc2V0IG9mIGRhdGEgb24gdGhlIHNlbGxpbmcgcHJpY2UgJFkkIChpbiBcJDEwLDAwMCkgYW5kIGFubnVhbCB0YXhlcyAkWCQgKGluIFwkMSwwMDApIGZvciAyNApob3VzZXMgaXMgYXZhaWxhYmxlIGF2YWlsYWJsZSBvbmxpbmUsIHtob3VzZXNlbGxpbmdwcmljZS50eHR9LgoKCmEuIEFzc3VtaW5nIHRoYXQgYSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgaXMgYXBwcm9wcmlhdGUsCm9idGFpbiB0aGUgbGVhc3Qgc3F1YXJlcyBmaXQgcmVsYXRpbmcgc2VsbGluZyBwcmljZSB0byB0YXhlcyBwYWlkLgpXaGF0IGlzIHRoZSBlc3RpbWF0ZSBvZiAkXHNpZ21hXjIkPwoKClJlYWQgZGF0YSBpbgoKYGBge3Igc2l6ZT0ic2NyaXB0c2l6ZSJ9CmhvdXNlID0gcmVhZC50YWJsZSgiaG91c2VzZWxsaW5ncHJpY2UudHh0IixoZWFkZXI9VCkKc3VtbWFyeShob3VzZSkKYGBgCgpTaW1wbGUgTGluZWFyIHJlZ3Jlc3Npb24gZml0CgpgYGB7ciBzaXplPSJzY3JpcHRzaXplIn0KaG91c2UubG08LWxtKHNhbGVzfnRheGVzLGRhdGE9aG91c2UpCnN1bW1hcnkoaG91c2UubG0pCmBgYAoKJFx3aWRlaGF0XGJldGFfMD0xMy4zMjAyJCwgJFx3aWRlaGF0XGJldGFfMT0zLjMyNDQkCgpgYGB7ciBzaXplPSJzY3JpcHRzaXplIn0KYW5vdmEoaG91c2UubG0pCmBgYAoKJFx3aWRlaGF0XHNpZ21hXjI9e1Jlc2lkdWFsIE1TfT04Ljc3JAoKCmIuIEZpbmQgdGhlIG1lYW4gc2VsbGluZyBwcmljZSBnaXZlbiB0aGF0IHRoZSB0YXhlcyBwYWlkIGFyZSAkNy41MCQuCgoKYGBge3Igc2l6ZT0ic2NyaXB0c2l6ZSJ9CnByZWRpY3QoaG91c2UubG0sbmV3ZGF0YT1kYXRhLmZyYW1lKHRheGVzPTcuNSksaW50ZXJ2YWw9ImNvbmZpZGVuY2UiLGxldmVsPTAuOTUpCmBgYAoKdGhlIG1lYW4gc2VsbGluZyBwcmljZSAkPTM4LjI1Mjk2JCB0aGF0IHRoZSB0YXhlcyBwYWlkIGFyZSAkWF8wPTcuNTAkLgoKCmMuIENvbnN0cnVjdCBhIGdyYXBoIG9mICRZJCB2ZXJzdXMgJFgkLiBUaGVuIGFkZCB0aGUgZml0dGVkIGxpbmUsCnRoZSA5NVwlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhlIG1lYW4gcmVzcG9uc2UsIGFuZCB0aGUgOTVcJQpwcmVkaWN0aW9uIGludGVydmFsIG9mIHRoZSBuZXcgYWN0dWFsIHZhbHVlcyBvbiB0aGUgZ3JhcGguCgoKYGBge3Igc2l6ZT0ic2NyaXB0c2l6ZSJ9CndpdGgoaG91c2UscGxvdChzYWxlc350YXhlcyx0eXBlPSJwIikpCndpdGgoaG91c2UsbGluZXMoZml0dGVkKGhvdXNlLmxtKX50YXhlcykpCm5ldyA9IGRhdGEuZnJhbWUodGF4ZXM9c2VxKDMsMTAsLjEpKQpDSXMgPSBwcmVkaWN0KGhvdXNlLmxtLG5ldyxpbnRlcnZhbD0iY29uZmlkZW5jZSIpClBJcyA9IHByZWRpY3QoaG91c2UubG0sbmV3LGludGVydmFsPSJwcmVkaWN0IikKbWF0cG9pbnRzKG5ldyR0YXhlcyxDSXMsbHR5PWMoMSwyLDIpLGNvbD1jKCJibGFjayIsInJlZCIsInJlZCIpLHR5cGU9ImwiKQptYXRwb2ludHMobmV3JHRheGVzLFBJcyxsdHk9YygxLDIsMiksY29sPWMoImJsYWNrIiwiYmx1ZSIsImJsdWUiKSx0eXBlPSJsIikKYGBgCgoKZC4gUGVyZm9ybSBkaWFnbm9zdGljIGNoZWNraW5nIGZvciB0aGUgZml0dGVkIG1vZGVsIGluIChhKSB1c2luZyDigJxwbG90KGZpbGUubG0pLuKAnSBJbnRlcnByZXQgdGhlIG91dHB1dHMuCgpgYGB7cn0KcGFyKG1mcm93PWMoMiwyKSkKcGxvdChob3VzZS5sbSkKYGBgCgoKKyBUaGUgdG9wIGxlZnQgcGxvdCBzaG93cyB0aGUgcmVzaWR1YWxzIGFnYWluc3QgZml0dGVkIHZhbHVlcyB0byBjaGVjayByYW5kb21uZXNzIChubyBwYXR0ZXJuKSBhbmQgbGluZWFyaXR5LiAKVGhlIHNtb290aGluZyBjdXJ2ZSBzaG93cyBhIHJlYXNvbmFibGUgbGluZWFyIHJlbGF0aW9uc2hpcCBhbmQgbm8gcGF0dGVybi4KCisgVGhlIGJvdHRvbSBsZWZ0IHByb3ZpZGVzIHRoZSBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIGFnYWluc3QgZml0dGVkIHZhbHVlcyB0byBjaGVjayByYW5kb21uZXNzIChubyBwYXR0ZXJuKSBhbmQgY29uc3RhbnQgdmFyaWFuY2UuIFRoZSBzbW9vdGhpbmcgY3VydmUgdXNpbmcgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBpcyBhIGN1cnZlIHdoaWNoIG1lYW5zIHRoYXQgaW5kZXBlbmRlbmNlIGFuZCBjb25zdGFudCB2YXJpYW5jZSBtYXkgbm90IGJlIHNhdGlzZmllZC4KCisgVGhlIHRvcCByaWdodCBwbG90IGlzIGEgbm9ybWFsIFHigJNRIHBsb3QuIE1vc3Qgb2YgdGhlIG9ic2VydmF0aW9ucyBsaWUgYXJvdW5kIHRoZSBzdHJhaWdodCBsaW5lIGV4Y2VwdCB0aGUgdHdvIHBvaW50cywgY29uZmlybWluZyBOb3JtYWxpdHkuCgorIFRoZSBib3R0b20gcmlnaHQgcGxvdCBvZiBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzIGFnYWluc3QgbGV2ZXJhZ2UgZW5hYmxlcyBvbmUKdG8gcmVhZGlseSBpZGVudGlmeSBhbnkg4oCYYmFk4oCZIGxldmVyYWdlIHBvaW50cy4gCgpgYGB7cn0KIyBjaGVjayBoZWxwIGZ1bmN0aW9uIGZpcnN0CmhvdXNlLmxldjwtaGF0dmFsdWVzKGhvdXNlLmxtKQpob3VzZS5sZXYKYGBgCmBgYHtyfQpzdGQucmVzLmg9cnN0YW5kYXJkKGhvdXNlLmxtKQojc3RkLnJlcy5oCnNvcnQoc3RkLnJlcy5oKQpgYGAKCiAgICAgICAgLSBSZWNhbGwgdGhhdCB0aGUgcnVsZSBmb3Igc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIGZvciBjbGFzc2lmeWluZyBhIHBvaW50IGFzIGEgbGV2ZXJhZ2UKICAgICAgICBwb2ludCBpcyBpZiBsZXZlcmFnZSAkaF97aWl9ID4gNC8gbi4kIEFzICRuPTI0JCwgdGhlIHJ1bGUgaXMgJGhfe2lpfSA+IDAuMTY3LiQgQXMgbGV2ZXJhZ2UgJGhfe2lpfSQgaW4gdGhlICAKICAgICAgICBhYm92ZSBvdXRwdXQgc2hvd3MgdGhhdCBvbmUgcG9pbnQgKG9ic2VydmF0aW9uIG5vIDI0KSB3aXRoICRoX3tpaX09MC4xNzE3NyA+IDAuMTY3JCAsIHRoZW4gdGhlcmUgaXMgb25lCiAgICAgICAgbGV2ZXJhZ2UgcG9pbnQuCgogICAgICAgIC0gUmVjYWxsIHRoYXQgd2UgY2xhc3NpZnkgcG9pbnRzIGFzIG91dGxpZXJzIGlmIHRoZWlyIHN0YW5kYXJkaXplZCByZXNpZHVhbHMgaGF2ZQogICAgICAgIGFic29sdXRlIHZhbHVlIGdyZWF0ZXIgdGhhbiAyLiBUaGVyZSBpcyBvbmUgb2JzZXJ2YXRpb24gKG5vIDE1KSB3aXRoIHRoZSBzdGFuZGFyZCByZXNpZHVhbCBpcyBncmVhdGVyIHRoYW4gIAogICAgICAgIDIuIEhvd2V2ZXIgb2JzZXJ2YXRpb24gbnVtYmVyIDI0LCB0aGUgbGV2ZXJhZ2UgcG9pbnQsICB3aXRoIHN0YW5kYXJkIHJlc2lkdWFsIGxlc3MgdGhhbiAyIGlzIGEgZ29vZAogICAgICAgIGxldmVyYWdlIHBvaW50LgogICAgICAgIAogICAgICAgIAojIyBRdWVzdGlvbiA1IEJpZCBkYXRhIChTaGVhdGhlciwgMjAwOSkKCkEgYnVpbGRpbmcgbWFpbnRlbmFuY2UgY29tcGFueSBpcyBwbGFubmluZyB0byBzdWJtaXQgYSBiaWQgb24gYSBjb250cmFjdCB0byBjbGVhbiBjb3Jwb3JhdGUKb2ZmaWNlcyBzY2F0dGVyZWQgdGhyb3VnaG91dCBhbiBvZmZpY2UgY29tcGxleC4gVGhlIGNvc3RzIGluY3VycmVkIGJ5IHRoZSBtYWludGVuYW5jZSBjb21wYW55IGFyZQpwcm9wb3J0aW9uYWwgdG8gdGhlIG51bWJlciBvZiBjbGVhbmluZyBjcmV3cyBuZWVkZWQgZm9yIHRoaXMgdGFzay4gUmVjZW50IGRhdGEgYXJlIGF2YWlsYWJsZSBmb3IgdGhlIG51bWJlcgpvZiByb29tcyB0aGF0IHdlcmUgY2xlYW5lZCBieSB2YXJ5aW5nIG51bWJlcnMgb2YgY3Jld3MuIEZvciBhIHNhbXBsZSBvZiA1MyBkYXlzLCByZWNvcmRzIHdlcmUga2VwdCBvZiB0aGUgCm51bWJlciBvZiBjcmV3cyB1c2VkIGFuZCB0aGUgbnVtYmVyIG9mIHJvb21zIHRoYXQgd2VyZSBjbGVhbmVkIGJ5IHRob3NlIGNyZXdzLgpUaGUgZGF0YSBjYW4gYmUgZm91bmQgaW4gdGhlIGZpbGUgKmNsZWFuaW5nLnR4dCouCgpUaGUgYWltIGlzIHRvIGRldmVsb3AgYSByZWdyZXNzaW9uIGVxdWF0aW9uIHRvIG1vZGVsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgCm51bWJlciBvZiByb29tcyBjbGVhbmVkIGFuZCB0aGUgbnVtYmVyIG9mIGNyZXdzLgoKQ29tcGxldGUgdGhlIGZvbGxvd2luZyB0YXNrcy4KCihhKS4gRml0IHRoZSBsZWFzdCBzcXVhcmVzIGxpbmUgdG8gdGhlIGRhdGEgdXNpbmcgUi4gRXhwbGFpbiB0aGUgZml0dGVkIG1vZGVsLCBieSBpbnRlcnByZXRpbmcgdGhlIHNsb3BlIGFuZCBpbnRlcmNlcHQuCgpgYGB7cn0KYmlkPXJlYWQudGFibGUoImNsZWFuaW5nLnR4dCIsIGhlYWRlcj1UKQpoZWFkKGJpZCkKYGBgCgpgYGB7cn0KYmlkLmxtPWxtKFJvb21zIH4gQ3Jld3MsIGRhdGE9YmlkKSAjIyB0aGUgTFMgbGluZQpwbG90KFJvb21zIH4gQ3Jld3MsIGRhdGE9YmlkLCB4bGFiPSJOdW1iZXIgb2YgQ3Jld3MiLCB5bGFiPSJOdW1iZXIgb2YgUm9vbXMiKQphYmxpbmUoYmlkLmxtKQpzdW1tYXJ5KGJpZC5sbSkKYGBgCgpUaGUgZXF1YXRpb24gb2YgdGhlIGxlYXN0IHNxdWFyZXMgbGluZSBvZiBiZXN0IGZpdCBpcwoKJCRSb29tcyA9IDEuNzggKyAzLjcwIENyZXdzLiQkCgoKVGhlIGludGVyY2VwdCBpcyAkMS43OCBcYXBwcm94IDIkIHdoaWNoIGlzIHdoZXJlIHRoZSBsaW5lIG9mIGJlc3QgZml0IGNyb3NzZXMgdGhlIFJvb21zIGF4aXMuIFRoZQppbnRlcmNlcHQgaW4gdGhlIG1vZGVsIGhhcyB0aGUgZm9sbG93aW5nIGludGVycHJldGF0aW9uOiBmb3IgQ3Jld3M9MCwgdGhlCmF2ZXJhZ2Ugb2YgbnVtYmVyIG9mIGNsZWFuZWQgcm9vbSBpcyAyLgoKVGhlIHNsb3BlIG9mIHRoZSBsaW5lIGlzICQzLjcwIFxhcHByb3ggNCQuIFRodXMsIHdlIHNheSB0aGF0IGZvciBlYWNoCmFkZGl0aW9uYWwgY3JldywgaXQgaXMgcHJlZGljdGVkIHRvIGFkZCA0IHJvb21zIGFyZSBiZWluZyBjbGVhbmVkLiAKCihiKS4gQ29uc3RydWN0IHJlc2lkdWFsIGRpYWdub3N0aWMgcGxvdHMsIGFuZCBhc3Nlc3Mgd2hldGhlciB5b3UgdGhpbmsgdGhhdCB0aGUgYXNzdW1wdGlvbnMgZm9yIGxpbmVhciByZWdyZXNzaW9uIGhhdmUgYmVlbiBzYXRpc2ZpZWQuIFlvdSBjYW4gdXNlIHRoZSBmdW5jdGlvbiBgcnN0dWRlbnRgIChvciBgcnN0YW5kYXJkYCkgdG8gZmlyc3Qgc3RhbmRhcmRpemUgdGhlIHJlc2lkdWFscy4KCkZpcnN0LCB3ZSBtYW51YWxseSBjaGVjayB0aGUgKm5vcm1hbGl0eSB0aHJvdWdoIGhpc3RvZ3JhbXMgYW5kIFFRLXBsb3RzIG9mIHJlc2lkdWFscyBhbmQgc3RhbmRhcmRpc2VkIHJlc2lkdWFscy4qCgpgYGB7cn0KcmVzLmJpZD1iaWQubG0kcmVzaWR1YWxzCnN0ZC5yZXMuYmlkPXJzdGFuZGFyZChiaWQubG0pICAjIyBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzCnBhcihtZnJvdz1jKDIsMikpICAjIyBwbG90dGluZyA0IHBsb3RzIHRvIGNoZWNrIG5vcm1hbGl0eQpoaXN0KHJlcy5iaWQpCmhpc3Qoc3RkLnJlcy5iaWQpCnFxbm9ybShyZXMuYmlkKQpxcWxpbmUocmVzLmJpZCkKcXFub3JtKHN0ZC5yZXMuYmlkKQpxcWxpbmUoc3RkLnJlcy5iaWQpCnBhcihtZnJvdz1jKDEsMSkpCmBgYAoKRnJvbSB0aGUgYWJvdmUgaGlzdG9ncmFtcyBhbmQgUVEtcGxvdHMsIHRoZSBub3JtYWxpdHkgaXMgc2F0aXNmaWVkLgoKYGBge3J9CnBhcihtZnJvdz1jKDIsMikpCnBsb3QocmVzLmJpZCwgeGxhYj0iVGltZSIsIHlsYWI9IlJlc2lkdWFscyIpICMjIFJlc2lkdWFscyB2cyBUaW1lCnBsb3Qoc3RkLnJlcy5iaWQseGxhYj0iVGltZSIsIHlsYWI9IlN0YW5kYXJkaXNlZCBSZXNpZHVhbHMiKQpwbG90KGJpZCRDcmV3cyxyZXMuYmlkLCB4bGFiPSJOdW1iZXIgb2YgQ3Jld3MiLCB5bGFiPSJSZXNpZHVhbHMiKSAjIFJlc2lkdWFscyB2cyB4CnBsb3QoYmlkJENyZXdzLHN0ZC5yZXMuYmlkLCAgeGxhYj0iTnVtYmVyIG9mIENyZXdzIiwgeWxhYj0iU3RhbmRhcmRpc2VkIFJlc2lkdWFscyIpCmBgYAoKICAgICAtIFRoZSBuZXh0IHJlc2lkdWFsIGFuYWx5c2lzIGlzIHRvIGNoZWNrIGFib3V0IHJhbmRvbW5lc3MgKGluZGVwZW5kZW5jZSkgYW5kIGNvbnN0YW50IHZhcmlhbmNlLiBXZSBwbG90IGJvdGgKICAgICByZXNpZHVhbHMgYW5kIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMgYWdhaW5zdCB0aW1lICh0b3AgbGVmdCBhbmQgdG9wIHJpZ2h0KS4gRnJvbSB0aGVzZSBwbG90cyB3ZSBjYW4gY29uZmlybSB0aGUKICAgICB0aGUgcmVzaWR1YWwgYXJlIHJhbmRvbSBzY2F0dGVyZWQgd2l0aCBubyBwYXR0ZXJuIHdoYXRzb2V2ZXIuIEhvd2V2ZXIsIHRoZXJlIHNlZW1zIHRvIHNob3cgYW4gaW5jcmVhc2luZyB0cmVuZCBmb3IgdmFyaWFuY2VzLgoKICAgICAtIFRoZSBib3R0b20gbGVmdCBwbG90IHNob3dzIHRoZSByZXNpZHVhbHMgYWdhaW5zdCBOdW1iZXIgb2YgQ3Jld3MgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8gcGF0dGVybikgYW5kIGNvbnN0YW50IHZhcmlhbmNlLiBUaGUgYm90dG9tIHJpZ2h0IHBsb3QgcHJvdmlkZXMgdGhlIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMgYWdhaW5zdCBmaXR0ZWQgdmFsdWVzIHRvIGNoZWNrIHJhbmRvbW5lc3MgKG5vIHBhdHRlcm4pIGFuZCBjb25zdGFudCB2YXJpYW5jZS4gCiAgCiAgICAtIEl0IGlzIGNsZWFyIHRoYXQgIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgc3RhbmRhcmRpemVkIHJlc2lkdWFscyB0ZW5kcyB0byBpbmNyZWFzZSAgd2l0aCB0aGUgbnVtYmVyIG9mIGNyZXdzLiBUaHVzLCB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSB2YXJpYW5jZSBvZiB0aGUgZXJyb3JzIGlzIGNvbnN0YW50IGFwcGVhcnMgdG8gYmUgdmlvbGF0ZWQgaW4gdGhpcyBjYXNlLiAKCihjKS4gUGVyZm9ybSBkaWFnbm9zdGljIGNoZWNraW5nIGZvciB0aGUgZml0dGVkIG1vZGVsIGluIChhKSB1c2luZyAicGxvdChmaWxlLmxtKS4iIEludGVycHJldCB0aGUgb3V0cHV0cy4KCmBgYHtyfQpwYXIobWZyb3c9YygyLDIpKQpwbG90KGJpZC5sbSkKYGBgCgogICAgICAgLSAgVGhlIHRvcCBsZWZ0IHBsb3Qgc2hvd3MgdGhlIHJlc2lkdWFscyBhZ2FpbnN0IGZpdHRlZCB2YWx1ZXMgdG8gY2hlY2sgcmFuZG9tbmVzcyAobm8gcGF0dGVybikgYW5kIGxpbmVhcml0eS4gIFRoZSBzbW9vdGhpbmcgY3VydmUgc2hvd3MgYSByZWFzb25hYmxlIGxpbmVhciByZWxhdGlvbnNoaXAgYW5kIG5vIHBhdHRlcm4uCgogICAgICAgLSBUaGUgYm90dG9tIGxlZnQgcHJvdmlkZXMgdGhlIHNxdWFyZWQgcm9vdCBvZiBzdGFuZGFyZGlzZWQgcmVzaWR1YWxzIGFnYWluc3QgZml0dGVkIHZhbHVlcyB0byBjaGVjayByYW5kb21uZXNzIChubyBwYXR0ZXJuKSBhbmQgY29uc3RhbnQgdmFyaWFuY2UuIFRoZSBzbW9vdGhpbmcgY3VydmUgdXNpbmcgc3RhbmRhcmRpc2VkIHJlc2lkdWFscyBpcyBhbiBpbmNyZWFzaW5nIHRyZW5kIHdoaWNoIG1lYW5zIHRoYXQgY29uc3RhbnQgdmFyaWFuY2UgbWF5IG5vdCBiZSBzYXRpc2ZpZWQuCgogICAgICAgIC0gVGhlIHRvcCByaWdodCBwbG90IGlzIGEgbm9ybWFsIFHigJNRIHBsb3QuIE1vc3Qgb2YgdGhlIG9ic2VydmF0aW9ucyBsaWUgYXJvdW5kIHRoZSBzdHJhaWdodCBsaW5lIGV4Y2VwdCB0aGUgdHdvIHBvaW50cywgY29uZmlybWluZyBOb3JtYWxpdHkuCgogICAgICAgIC0gIFRoZSBib3R0b20gcmlnaHQgcGxvdCBvZiBzdGFuZGFyZGl6ZWQgcmVzaWR1YWxzIGFnYWluc3QgbGV2ZXJhZ2UgZW5hYmxlcyBvbmUgdG8gcmVhZGlseSBpZGVudGlmeSBhbnkg4oCYYmFk4oCZIGxldmVyYWdlIHBvaW50cyAoaWUgbGFyZ2UgbGV2ZXJhZ2UgYW5kIGxhcmdlIHN0YW5kYXJkaXNlZCByZXNpZHVhbHMpIAoKKGQpLiBBcyB0aGUgIGRhdGEgIG9uIGVhY2ggYXhpcyBhcmUgIGluIHRoZSBmb3JtIG9mIGNvdW50cyBhbmQgYXJlIG1lYXN1cmVkIGluIHRoZSBzYW1lIHVuaXRzLCB0aGUgc3F1YXJlIApyb290IHRyYW5zZm9ybWF0aW9uIG9mIGJvdGggdGhlIHByZWRpY3RvciB2YXJpYWJsZSBhbmQgdGhlIHJlc3BvbnNlIHZhcmlhYmxlIHNob3VsZCBiZSBpbXBsZW1lbnRlZC4gQXBwbHkgCnRoZXNlIHRyYW5zZm9ybWF0aW9ucyBhbmQgcmVwZWF0IChhKS4KCgpgYGB7cn0KYmlkLnNxLmxtPWxtKHNxcnQoUm9vbXMpIH4gc3FydChDcmV3cyksIGRhdGE9YmlkKSAjIyB0aGUgTFMgbGluZQpwbG90KHNxcnQoUm9vbXMpIH4gc3FydChDcmV3cyksIGRhdGE9YmlkLCB4bGFiPSJTcXVhcmUgUm9vdCBvZiBOdW1iZXIgb2YgQ3Jld3MiLCB5bGFiPSJTcXVhcmUgUm9vdCBvZiBOdW1iZXIgb2YgUm9vbXMiKQphYmxpbmUoYmlkLnNxLmxtKQpzdW1tYXJ5KGJpZC5zcS5sbSkKYGBgCgooZSkuIFBlcmZvcm0gZGlhZ25vc3RpYyBjaGVja2luZyBmb3IgdGhlIGZpdHRlZCBtb2RlbCBpbiAoZCkgdXNpbmcgInBsb3QoZmlsZS5sbSkuIiBJbnRlcnByZXQgdGhlIG91dHB1dHMuCgoKYGBge3J9CnBhcihtZnJvdz1jKDIsMikpCnBsb3QoYmlkLnNxLmxtKQpgYGAKCgogICAgICAgICAtIEFmdGVyIHRoZSB0cmFuc2Zvcm1hdGlvbiwgdGhlIGJvdHRvbSBsZWZ0LWhhbmQgcGxvdCBmdXJ0aGVyIGRlbW9uc3RyYXRlcyB0aGUgCiAgICAgICAgIGJlbmVmaXQgb2YgdGhlIHNxdWFyZSByb290IHRyYW5zZm9ybWF0aW9uIGluIHRlcm1zIG9mIHN0YWJpbGl6aW5nIHRoZSBlcnJvciB0ZXJtLiAgCiAgICAgICAgIAogICAgICAgICAtIFRodXMsIHRha2luZyB0aGUgc3F1YXJlIHJvb3Qgb2YgYm90aCB0aGUgIHggIGFuZCB0aGUgIHkgIHZhcmlhYmxlcyBoYXMgc3RhYmlsaXplZAogICAgICAgICB0aGUgdmFyaWFuY2Ugb2YgdGhlIHJhbmRvbSBlcnJvcnMgYW5kIGhlbmNlIHByb2R1Y2VkIGEgdmFsaWQgbW9kZWwuICAKCgooZikuIFByZWRpY3QgdGhlIG51bWJlciBvZiByb29tcyB0aGF0IGNhbiBiZSBjbGVhbmVkIGJ5IDQgY3Jld3MgYW5kIGJ5IDE2IGNyZXdzIGFuZCBpdHMgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHVzaW5nIHRoZSBtb2RlbHMgaW4gKGEpIGFuZCAoZCkgcmVzcGVjdGl2ZWx5LgoKVXNpbmcgKGEpCgpgYGB7cn0KY29uZi5wcmVkMD1wcmVkaWN0KGJpZC5sbSxuZXdkYXRhPWRhdGEuZnJhbWUoQ3Jld3M9Yyg0LDE2KSksaW50ZXJ2YWw9InByZWRpY3Rpb24iLGxldmVsPTAuOTUpCmNvbmYucHJlZDAKYGBgCgpVc2luZyAoZCkKCmBgYHtyfQpjb25mLnByZWQwLnNxPXByZWRpY3QoYmlkLnNxLmxtLG5ld2RhdGE9ZGF0YS5mcmFtZShDcmV3cz1jKDQsMTYpKSxpbnRlcnZhbD0icHJlZGljdGlvbiIsbGV2ZWw9MC45NSkKY29uZi5wcmVkMC5zcV4yICAjIyBhcyB0aGlzIHdhcyBzcXVhcmUgcm9vdApgYGAKCiAgICAgICAtIFdlIGNhbiBzZWUgdGhhdCB0aGUgcHJlZGljdGlvbiBpbnRlcnZhbCBiYXNlZCBvbiB0aGUgdHJhbnNmb3JtZWQgZGF0YSBpcyBuYXJyb3dlciAKICAgICAgIHRoYW4gdGhhdCAgYmFzZWQgb24gdGhlIHVudHJhbnNmb3JtZWQgZGF0YSB3aGVuIHRoZSBudW1iZXIgb2YgY3Jld3MgaXMgNCAoNy43OCwgCiAgICAgICAyNy4yMSkgdnMgKDEuNTgsIDMxLjU5KSBhbmQgd2lkZXIgd2hlbiB0aGUgbnVtYmVyIG9mIGNyZXdzIGlzIDE2IFsoNDMuMzMsIDgxLjU1KSBpcyAKICAgICAgIHdpZGVyIHRoYW4gKDQ1LjgxLCA3Ni4xOSldLiAKCiAgICAgICAtIFRoaXMgaXMgZXhwZWN0ZWQgYXMgdGhlIG9yaWdpbmFsIHNjYWxlIHRoZSBkYXRhIGhhdmUgdmFyaWFuY2Ugd2hpY2ggaW5jcmVhc2VzIGFzIAogICAgICAgdGhlICB4IC12YXJpYWJsZSBpbmNyZWFzZXMgd2hpY2ggbWVhbnMgdGhhdCByZWFsaXN0aWMgcHJlZGljdGlvbiBpbnRlcnZhbHMgd2lsbAogICAgICAgZ2V0IHdpZGVyIGFzIHRoZSAgeCAtdmFyaWFibGUgaW5jcmVhc2VzLiAgCgogICAgICAtIEluIHN1bW1hcnksIGlnbm9yaW5nIG5vbmNvbnN0YW50IHZhcmlhbmNlIGluIHRoZSByYXcgZGF0YSBmcm9tIHRoaXMgZXhhbXBsZSBsZWQgdG8gCiAgICAgIGludmFsaWQgcHJlZGljdGlvbiBpbnRlcnZhbHMuIAogICAgICAKICAgICAg